refactored CB SDC generation

This commit is contained in:
tangxifan 2019-11-09 11:42:38 -07:00
parent 4b5ecc516b
commit a7f2a61d0d
2 changed files with 234 additions and 11 deletions

View File

@ -527,7 +527,7 @@ void print_pnr_sdc_constrain_sb_timing(const std::string& sdc_dir,
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Constrain timing of Switch Block " + sb_module_name + " outputs for PnR"));
print_sdc_file_header(fp, std::string("Constrain timing of Switch Block " + sb_module_name + " for PnR"));
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
Side side_manager(side);
@ -594,9 +594,7 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_di
}
/********************************************************************
* 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
* Print SDC timing constraints for Switch blocks
* This function is designed for compact routing hierarchy
*******************************************************************/
static
@ -628,6 +626,227 @@ void print_pnr_sdc_compact_routing_constrain_sb_timing(const std::string& sdc_di
run_time_sec);
}
/********************************************************************
* Set timing constraints between the inputs and outputs of a routing
* multiplexer in a Connection Block
*******************************************************************/
static
void print_pnr_sdc_constrain_cb_mux_timing(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& cb_module,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& switches,
t_rr_node* output_rr_node) {
/* Validate file stream */
check_file_handler(fp);
VTR_ASSERT(IPIN == output_rr_node->type);
/* Find the module port corresponding to the output rr_node */
ModulePortId module_output_port = find_connection_block_module_ipin_port(module_manager,
cb_module,
rr_gsb,
grids, output_rr_node);
/* Find the module port corresponding to the fan-in rr_nodes of the output rr_node */
std::vector<t_rr_node*> input_rr_nodes;
for (int iedge = 0; iedge < output_rr_node->num_drive_rr_nodes; iedge++) {
input_rr_nodes.push_back(output_rr_node->drive_rr_nodes[iedge]);
}
std::vector<ModulePortId> module_input_ports = find_connection_block_module_input_ports(module_manager,
cb_module,
rr_gsb,
cb_type,
input_rr_nodes);
/* Find timing constraints for each path (edge) */
std::map<ModulePortId, float> switch_delays;
for (int iedge = 0; iedge < output_rr_node->num_drive_rr_nodes; iedge++) {
/* Get the switch delay */
int switch_id = output_rr_node->drive_switches[iedge];
switch_delays[module_input_ports[iedge]] = find_pnr_sdc_switch_tmax(switches[switch_id]);
}
/* Find the starting points */
for (const ModulePortId& module_input_port : module_input_ports) {
/* Constrain a path */
print_pnr_sdc_constrain_module_port2port_timing(fp,
module_manager, cb_module,
module_input_port, module_output_port,
switch_delays[module_input_port]);
}
}
/********************************************************************
* Print SDC timing constraints for a Connection block
* This function is designed for compact routing hierarchy
*******************************************************************/
static
void print_pnr_sdc_constrain_cb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& switches) {
/* Create the netlist */
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
/* Find the module name and create a SDC file for it */
std::string sdc_fname(sdc_dir + generate_connection_block_module_name(cb_type, gsb_coordinate) + std::string(SDC_FILE_NAME_POSTFIX));
/* Create the file stream */
std::fstream fp;
fp.open(sdc_fname, std::fstream::out | std::fstream::trunc);
/* Validate file stream */
check_file_handler(fp);
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));
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Constrain timing of Connection Block " + cb_module_name + " for PnR"));
std::vector<enum e_side> cb_sides = rr_gsb.get_cb_ipin_sides(cb_type);
for (size_t side = 0; side < cb_sides.size(); ++side) {
enum e_side cb_ipin_side = cb_sides[side];
Side side_manager(cb_ipin_side);
for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(cb_ipin_side); ++inode) {
t_rr_node* ipin_rr_node = rr_gsb.get_ipin_node(cb_ipin_side, inode);
print_pnr_sdc_constrain_cb_mux_timing(fp,
module_manager, cb_module,
rr_gsb, cb_type,
grids, switches,
ipin_rr_node);
}
}
/* Close file handler */
fp.close();
}
/********************************************************************
* Iterate over all the connection blocks in a device
* and print SDC file for each of them
*******************************************************************/
static
void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const DeviceRRGSB& L_device_rr_gsb,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& switches,
const t_rr_type& cb_type) {
/* Build unique X-direction connection block modules */
DeviceCoordinator cb_range = L_device_rr_gsb.get_gsb_range();
for (size_t ix = 0; ix < cb_range.get_x(); ++ix) {
for (size_t iy = 0; iy < cb_range.get_y(); ++iy) {
/* Check if the connection block exists in the device!
* Some of them do NOT exist due to heterogeneous blocks (height > 1)
* We will skip those modules
*/
const RRGSB& rr_gsb = L_device_rr_gsb.get_gsb(ix, iy);
if (false == rr_gsb.is_cb_exist(cb_type)) {
continue;
}
print_pnr_sdc_constrain_cb_timing(sdc_dir,
module_manager,
rr_gsb,
cb_type,
grids, switches);
}
}
}
/********************************************************************
* Iterate over all the connection blocks in a device
* and print SDC file for each of them
*******************************************************************/
static
void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const DeviceRRGSB& L_device_rr_gsb,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& switches) {
vpr_printf(TIO_MESSAGE_INFO,
"Generating SDC for constrain Connection Block timing for P&R flow...");
/* Start time count */
clock_t t_start = clock();
print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_dir, module_manager,
L_device_rr_gsb,
grids,
switches,
CHANX);
print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_dir, module_manager,
L_device_rr_gsb,
grids,
switches,
CHANY);
/* End time count */
clock_t t_end = clock();
float run_time_sec = (float)(t_end - t_start) / CLOCKS_PER_SEC;
vpr_printf(TIO_MESSAGE_INFO,
"took %g seconds\n",
run_time_sec);
}
/********************************************************************
* Print SDC timing constraints for Connection blocks
* This function is designed for compact routing hierarchy
*******************************************************************/
static
void print_pnr_sdc_compact_routing_constrain_cb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<t_switch_inf>& switches,
const DeviceRRGSB& L_device_rr_gsb) {
vpr_printf(TIO_MESSAGE_INFO,
"Generating SDC for constrain Connection Block timing for P&R flow...");
/* Start time count */
clock_t t_start = clock();
/* Print SDC for unique X-direction connection block modules */
for (size_t icb = 0; icb < L_device_rr_gsb.get_num_cb_unique_module(CHANX); ++icb) {
const RRGSB& unique_mirror = L_device_rr_gsb.get_cb_unique_module(CHANX, icb);
print_pnr_sdc_constrain_cb_timing(sdc_dir,
module_manager,
unique_mirror,
CHANX,
grids, switches);
}
/* Print SDC for unique Y-direction connection block modules */
for (size_t icb = 0; icb < L_device_rr_gsb.get_num_cb_unique_module(CHANY); ++icb) {
const RRGSB& unique_mirror = L_device_rr_gsb.get_cb_unique_module(CHANY, icb);
print_pnr_sdc_constrain_cb_timing(sdc_dir,
module_manager,
unique_mirror,
CHANY,
grids, switches);
}
/* End time count */
clock_t t_end = clock();
float run_time_sec = (float)(t_end - t_start) / CLOCKS_PER_SEC;
vpr_printf(TIO_MESSAGE_INFO,
"took %g seconds\n",
run_time_sec);
}
/********************************************************************
* Top-level function to print a number of SDC files in different purpose
* This function will generate files upon the options provided by users
@ -698,18 +917,23 @@ void print_pnr_sdc(const SdcOption& sdc_options,
}
}
/* TODO: Output routing constraints for Connection Blocks */
/*
/* Output routing constraints for Connection Blocks */
if (true == sdc_options.constrain_cb()) {
if (true == compact_routing_hierarchy) {
verilog_generate_sdc_constrain_cbs(sdc_opts, LL_nx, LL_ny, LL_device_rr_gsb);
print_pnr_sdc_compact_routing_constrain_cb_timing(sdc_options.sdc_dir(),
module_manager,
grids,
switches,
L_device_rr_gsb);
} else {
VTR_ASSERT_SAFE (false == compact_routing_hierarchy);
verilog_generate_sdc_constrain_cbs(sdc_opts,
LL_nx, LL_ny);
print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_options.sdc_dir(),
module_manager,
L_device_rr_gsb,
grids,
switches);
}
}
*/
/* TODO: Output routing constraints for Programmable blocks */
/*

View File

@ -39,7 +39,6 @@ ModulePortId find_connection_block_module_ipin_port(const ModuleManager& module_
const std::vector<std::vector<t_grid_tile>>& grids,
t_rr_node* src_rr_node);
std::vector<ModulePortId> find_connection_block_module_input_ports(const ModuleManager& module_manager,
const ModuleId& cb_module,
const RRGSB& rr_gsb,