add refactored disable timing for memory cells
This commit is contained in:
parent
ea7c981c85
commit
e273c00c9d
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#include "fpga_x2p_naming.h"
|
||||||
#include "fpga_x2p_utils.h"
|
#include "fpga_x2p_utils.h"
|
||||||
|
|
||||||
#include "sdc_writer_naming.h"
|
#include "sdc_writer_naming.h"
|
||||||
|
@ -139,14 +140,70 @@ void print_pnr_sdc_global_ports(const std::string& sdc_dir,
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Break combintational loops in FPGA fabric, which mainly come from:
|
* Print SDC commands to disable outputs of all the configurable memory modules
|
||||||
|
* in a given module
|
||||||
|
* 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
|
||||||
|
*******************************************************************/
|
||||||
|
static
|
||||||
|
void rec_print_pnr_sdc_disable_configurable_memory_module_output(std::fstream& fp,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const ModuleId& parent_module,
|
||||||
|
const std::string& parent_module_path) {
|
||||||
|
|
||||||
|
/* 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];
|
||||||
|
if (true == module_manager.instance_name(parent_module, child_module_id, child_instance_id).empty()) {
|
||||||
|
/* Give a default name <module_name>_<instance_id>_ */
|
||||||
|
child_module_path += module_manager.module_name(child_module_id);
|
||||||
|
child_module_path += "_";
|
||||||
|
child_module_path += std::to_string(child_instance_id);
|
||||||
|
child_module_path += "_";
|
||||||
|
} else {
|
||||||
|
child_module_path += module_manager.instance_name(parent_module, child_module_id, child_instance_id);
|
||||||
|
}
|
||||||
|
child_module_path = format_dir_path(child_module_path);
|
||||||
|
|
||||||
|
rec_print_pnr_sdc_disable_configurable_memory_module_output(fp, module_manager,
|
||||||
|
child_module_id,
|
||||||
|
child_module_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there is no configurable children any more, this is a leaf module, print a SDC command for disable timing */
|
||||||
|
if (0 < module_manager.configurable_children(parent_module).size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate file stream */
|
||||||
|
check_file_handler(fp);
|
||||||
|
|
||||||
|
/* Disable timing for each output port of this module */
|
||||||
|
for (const BasicPort& output_port : module_manager.module_ports_by_type(parent_module, ModuleManager::MODULE_OUTPUT_PORT)) {
|
||||||
|
for (const size_t& pin : output_port.pins()) {
|
||||||
|
BasicPort output_pin(output_port.get_name(), pin, pin);
|
||||||
|
fp << "set_disable_timing ";
|
||||||
|
fp << parent_module_path << generate_sdc_port(output_pin);
|
||||||
|
fp << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Break combinational loops in FPGA fabric, which mainly come from:
|
||||||
* 1. Configurable memory cells.
|
* 1. Configurable memory cells.
|
||||||
* To handle this, we disable the outputs of memory cells
|
* To handle this, we disable the outputs of memory cells
|
||||||
* 2. Loops of multiplexers.
|
* 2. Loops of multiplexers.
|
||||||
* To handle this, we disable the outputs of routing multiplexers
|
* To handle this, we disable the outputs of routing multiplexers
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
static
|
static
|
||||||
void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_dir) {
|
void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_dir,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
|
const ModuleId& top_module) {
|
||||||
|
|
||||||
/* Create the file name for Verilog netlist */
|
/* Create the file name for Verilog netlist */
|
||||||
std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_CONFIG_MEM_OUTPUTS_FILE_NAME));
|
std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_CONFIG_MEM_OUTPUTS_FILE_NAME));
|
||||||
|
@ -165,7 +222,11 @@ void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_
|
||||||
check_file_handler(fp);
|
check_file_handler(fp);
|
||||||
|
|
||||||
/* Generate the descriptions*/
|
/* Generate the descriptions*/
|
||||||
print_sdc_file_header(fp, std::string("disable configurable memory outputs for PnR"));
|
print_sdc_file_header(fp, std::string("Disable configurable memory outputs for PnR"));
|
||||||
|
|
||||||
|
/* Go recursively in the module manager, starting from the top-level module: instance id of the top-level module is 0 by default */
|
||||||
|
rec_print_pnr_sdc_disable_configurable_memory_module_output(fp, module_manager, top_module,
|
||||||
|
format_dir_path(module_manager.module_name(top_module)));
|
||||||
|
|
||||||
/* Close file handler */
|
/* Close file handler */
|
||||||
fp.close();
|
fp.close();
|
||||||
|
@ -190,6 +251,7 @@ void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_
|
||||||
void print_pnr_sdc(const SdcOption& sdc_options,
|
void print_pnr_sdc(const SdcOption& sdc_options,
|
||||||
const float& critical_path_delay,
|
const float& critical_path_delay,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
const std::vector<CircuitPortId>& global_ports) {
|
const std::vector<CircuitPortId>& global_ports) {
|
||||||
|
|
||||||
/* Part 1. Constrain global ports */
|
/* Part 1. Constrain global ports */
|
||||||
|
@ -199,7 +261,10 @@ void print_pnr_sdc(const SdcOption& sdc_options,
|
||||||
|
|
||||||
/* Part 2. Output Design Constraints to disable outputs of memory cells */
|
/* Part 2. Output Design Constraints to disable outputs of memory cells */
|
||||||
if (true == sdc_options.constrain_configurable_memory_outputs()) {
|
if (true == sdc_options.constrain_configurable_memory_outputs()) {
|
||||||
print_pnr_sdc_constrain_configurable_memory_outputs(sdc_options.sdc_dir());
|
std::string top_module_name = generate_fpga_top_module_name();
|
||||||
|
ModuleId top_module = module_manager.find_module(top_module_name);
|
||||||
|
VTR_ASSERT(true == module_manager.valid_module_id(top_module));
|
||||||
|
print_pnr_sdc_constrain_configurable_memory_outputs(sdc_options.sdc_dir(), module_manager, top_module);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. Break loops from Multiplexer Output */
|
/* 2. Break loops from Multiplexer Output */
|
||||||
|
|
|
@ -5,11 +5,13 @@
|
||||||
#include "vtr_geometry.h"
|
#include "vtr_geometry.h"
|
||||||
#include "vpr_types.h"
|
#include "vpr_types.h"
|
||||||
#include "rr_blocks.h"
|
#include "rr_blocks.h"
|
||||||
|
#include "module_manager.h"
|
||||||
#include "sdc_option.h"
|
#include "sdc_option.h"
|
||||||
|
|
||||||
void print_pnr_sdc(const SdcOption& sdc_options,
|
void print_pnr_sdc(const SdcOption& sdc_options,
|
||||||
const float& critical_path_delay,
|
const float& critical_path_delay,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
const std::vector<CircuitPortId>& global_ports);
|
const std::vector<CircuitPortId>& global_ports);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
void fpga_sdc_generator(const SdcOption& sdc_options,
|
void fpga_sdc_generator(const SdcOption& sdc_options,
|
||||||
const float& critical_path_delay,
|
const float& critical_path_delay,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
const std::vector<CircuitPortId>& global_ports) {
|
const std::vector<CircuitPortId>& global_ports) {
|
||||||
vpr_printf(TIO_MESSAGE_INFO,
|
vpr_printf(TIO_MESSAGE_INFO,
|
||||||
"SDC generator starts...");
|
"SDC generator starts...");
|
||||||
|
@ -20,7 +21,7 @@ void fpga_sdc_generator(const SdcOption& sdc_options,
|
||||||
clock_t t_start = clock();
|
clock_t t_start = clock();
|
||||||
|
|
||||||
if (true == sdc_options.generate_sdc_pnr()) {
|
if (true == sdc_options.generate_sdc_pnr()) {
|
||||||
print_pnr_sdc(sdc_options.sdc_dir(), critical_path_delay, circuit_lib, global_ports);
|
print_pnr_sdc(sdc_options, critical_path_delay, circuit_lib, module_manager, global_ports);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End time count */
|
/* End time count */
|
||||||
|
@ -30,5 +31,4 @@ void fpga_sdc_generator(const SdcOption& sdc_options,
|
||||||
vpr_printf(TIO_MESSAGE_INFO,
|
vpr_printf(TIO_MESSAGE_INFO,
|
||||||
"SDC generation took %g seconds\n",
|
"SDC generation took %g seconds\n",
|
||||||
run_time_sec);
|
run_time_sec);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "sdc_option.h"
|
#include "sdc_option.h"
|
||||||
#include "circuit_library.h"
|
#include "circuit_library.h"
|
||||||
|
#include "module_manager.h"
|
||||||
|
|
||||||
void fpga_sdc_generator(const SdcOption& sdc_options,
|
void fpga_sdc_generator(const SdcOption& sdc_options,
|
||||||
const float& critical_path_delay,
|
const float& critical_path_delay,
|
||||||
const CircuitLibrary& circuit_lib,
|
const CircuitLibrary& circuit_lib,
|
||||||
|
const ModuleManager& module_manager,
|
||||||
const std::vector<CircuitPortId>& global_ports);
|
const std::vector<CircuitPortId>& global_ports);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -151,7 +151,7 @@ void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup,
|
||||||
src_dir = format_dir_path(src_dir);
|
src_dir = format_dir_path(src_dir);
|
||||||
}
|
}
|
||||||
SdcOption sdc_options(format_dir_path(src_dir + std::string(FPGA_X2P_DEFAULT_SDC_DIR)));
|
SdcOption sdc_options(format_dir_path(src_dir + std::string(FPGA_X2P_DEFAULT_SDC_DIR)));
|
||||||
sdc_options.set_generate_sdc_pnr(FALSE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_sdc_pnr);
|
sdc_options.set_generate_sdc_pnr(TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_sdc_pnr);
|
||||||
sdc_options.set_generate_sdc_analysis(TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_sdc_analysis);
|
sdc_options.set_generate_sdc_analysis(TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_sdc_analysis);
|
||||||
|
|
||||||
if (true == sdc_options.generate_sdc()) {
|
if (true == sdc_options.generate_sdc()) {
|
||||||
|
@ -159,7 +159,7 @@ void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup,
|
||||||
/* TODO: the critical path delay unit should be explicit! */
|
/* TODO: the critical path delay unit should be explicit! */
|
||||||
fpga_sdc_generator(sdc_options,
|
fpga_sdc_generator(sdc_options,
|
||||||
Arch.spice->spice_params.stimulate_params.vpr_crit_path_delay / 1e-9,
|
Arch.spice->spice_params.stimulate_params.vpr_crit_path_delay / 1e-9,
|
||||||
Arch.spice->circuit_lib, global_ports);
|
Arch.spice->circuit_lib, module_manager, global_ports);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Xifan Tang: Bitstream Generator */
|
/* Xifan Tang: Bitstream Generator */
|
||||||
|
|
Loading…
Reference in New Issue