refactoring analysis SDC generation
This commit is contained in:
parent
bcd8237263
commit
1f368abfbe
|
@ -0,0 +1,260 @@
|
|||
/********************************************************************
|
||||
* This file includes functions that are used to output a SDC file
|
||||
* that constrain a FPGA fabric (P&Red netlist) using a benchmark
|
||||
*******************************************************************/
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "vtr_assert.h"
|
||||
#include "device_port.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "mux_utils.h"
|
||||
|
||||
#include "fpga_x2p_naming.h"
|
||||
#include "fpga_x2p_utils.h"
|
||||
#include "fpga_x2p_benchmark_utils.h"
|
||||
|
||||
#include "sdc_writer_naming.h"
|
||||
#include "sdc_writer_utils.h"
|
||||
|
||||
#include "analysis_sdc_writer.h"
|
||||
|
||||
/********************************************************************
|
||||
* Generate SDC constaints for inputs and outputs
|
||||
* We consider the top module in formal verification purpose here
|
||||
* which is easier
|
||||
*******************************************************************/
|
||||
static
|
||||
void print_analysis_sdc_io_delays(std::fstream& fp,
|
||||
const std::vector<t_logical_block>& L_logical_blocks,
|
||||
const vtr::Point<size_t>& device_size,
|
||||
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
||||
const std::vector<t_block>& L_blocks,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::vector<CircuitPortId>& global_ports,
|
||||
const float& critical_path_delay) {
|
||||
/* Validate the file stream */
|
||||
check_file_handler(fp);
|
||||
|
||||
/* Print comments */
|
||||
fp << "##################################################" << std::endl;
|
||||
fp << "# Create clock " << std::endl;
|
||||
fp << "##################################################" << std::endl;
|
||||
|
||||
/* Get clock port from the global port */
|
||||
std::vector<BasicPort> operating_clock_ports;
|
||||
for (const CircuitPortId& clock_port : global_ports) {
|
||||
if (SPICE_MODEL_PORT_CLOCK != circuit_lib.port_type(clock_port)) {
|
||||
continue;
|
||||
}
|
||||
/* We only constrain operating clock here! */
|
||||
if (true == circuit_lib.port_is_prog(clock_port)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Update the operating port list */
|
||||
operating_clock_ports.push_back(BasicPort(circuit_lib.port_prefix(clock_port), circuit_lib.port_size(clock_port)));
|
||||
}
|
||||
|
||||
for (const BasicPort& operating_clock_port : operating_clock_ports) {
|
||||
/* Reach here, it means a clock port and we need print constraints */
|
||||
fp << "create_clock ";
|
||||
fp << generate_sdc_port(operating_clock_port);
|
||||
fp << " -period " << std::setprecision(10) << critical_path_delay;
|
||||
fp << " -waveform {0 " << std::setprecision(10) << critical_path_delay / 2 << "}";
|
||||
fp << std::endl;
|
||||
|
||||
/* Add an empty line as a splitter */
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
/* There should be only one operating clock!
|
||||
* TODO: this should be changed when developing multi-clock support!!!
|
||||
*/
|
||||
VTR_ASSERT(1 == operating_clock_ports.size());
|
||||
|
||||
/* In this function, we support only 1 type of I/Os */
|
||||
VTR_ASSERT(1 == module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIO_PORT).size());
|
||||
BasicPort module_io_port = module_manager.module_ports_by_type(top_module, ModuleManager::MODULE_GPIO_PORT)[0];
|
||||
|
||||
/* Keep tracking which I/Os have been used */
|
||||
std::vector<bool> io_used(module_io_port.get_width(), false);
|
||||
|
||||
/* Print comments */
|
||||
fp << "##################################################" << std::endl;
|
||||
fp << "# Create input and output delays for used I/Os " << std::endl;
|
||||
fp << "##################################################" << std::endl;
|
||||
|
||||
for (const t_logical_block& io_lb : L_logical_blocks) {
|
||||
/* We only care I/O logical blocks !*/
|
||||
if ( (VPACK_INPAD != io_lb.type) && (VPACK_OUTPAD != io_lb.type) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* clock net or constant generator should be disabled in timing analysis */
|
||||
if (TRUE == io_lb.is_clock) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find the index of the mapped GPIO in top-level FPGA fabric */
|
||||
size_t io_index = find_benchmark_io_index(io_lb, device_size, L_grids, L_blocks);
|
||||
|
||||
/* Ensure that IO index is in range */
|
||||
BasicPort module_mapped_io_port = module_io_port;
|
||||
/* Set the port pin index */
|
||||
VTR_ASSERT(io_index < module_mapped_io_port.get_width());
|
||||
module_mapped_io_port.set_width(io_index, io_index);
|
||||
|
||||
/* For input I/O, we set an input delay constraint correlated to the operating clock
|
||||
* For output I/O, we set an output delay constraint correlated to the operating clock
|
||||
*/
|
||||
if (VPACK_INPAD == io_lb.type) {
|
||||
print_sdc_set_port_input_delay(fp, module_mapped_io_port,
|
||||
operating_clock_ports[0], critical_path_delay);
|
||||
} else {
|
||||
VTR_ASSERT(VPACK_OUTPAD == io_lb.type);
|
||||
print_sdc_set_port_output_delay(fp, module_mapped_io_port,
|
||||
operating_clock_ports[0], critical_path_delay);
|
||||
}
|
||||
|
||||
/* Mark this I/O has been used/wired */
|
||||
io_used[io_index] = true;
|
||||
}
|
||||
|
||||
/* Add an empty line as a splitter */
|
||||
fp << std::endl;
|
||||
|
||||
/* Print comments */
|
||||
fp << "##################################################" << std::endl;
|
||||
fp << "# Disable timing for unused I/Os " << std::endl;
|
||||
fp << "##################################################" << std::endl;
|
||||
|
||||
/* Wire the unused iopads to a constant */
|
||||
for (size_t io_index = 0; io_index < io_used.size(); ++io_index) {
|
||||
/* Bypass used iopads */
|
||||
if (true == io_used[io_index]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Wire to a contant */
|
||||
BasicPort module_unused_io_port = module_io_port;
|
||||
/* Set the port pin index */
|
||||
module_unused_io_port.set_width(io_index, io_index);
|
||||
print_sdc_disable_port_timing(fp, module_unused_io_port);
|
||||
}
|
||||
|
||||
/* Add an empty line as a splitter */
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Top-level function outputs a SDC file
|
||||
* that constrain a FPGA fabric (P&Red netlist) using a benchmark
|
||||
*******************************************************************/
|
||||
void print_analysis_sdc(const std::string& sdc_dir,
|
||||
const float& critical_path_delay,
|
||||
const DeviceRRGSB& L_device_rr_gsb,
|
||||
const std::vector<t_logical_block>& L_logical_blocks,
|
||||
const vtr::Point<size_t>& device_size,
|
||||
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
||||
const std::vector<t_block>& L_blocks,
|
||||
const ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::vector<CircuitPortId>& global_ports,
|
||||
const bool& compact_routing_hierarchy) {
|
||||
/* Create the file name for Verilog netlist */
|
||||
std::string sdc_fname(sdc_dir + std::string(SDC_ANALYSIS_FILE_NAME));
|
||||
|
||||
vpr_printf(TIO_MESSAGE_INFO,
|
||||
"Generating SDC for Timing/Power analysis on the mapped FPGA: %s ...",
|
||||
sdc_fname.c_str());
|
||||
|
||||
/* Start time count */
|
||||
clock_t t_start = clock();
|
||||
|
||||
/* Create the file stream */
|
||||
std::fstream fp;
|
||||
fp.open(sdc_fname, std::fstream::out | std::fstream::trunc);
|
||||
|
||||
/* Validate file stream */
|
||||
check_file_handler(fp);
|
||||
|
||||
/* Generate the descriptions*/
|
||||
print_sdc_file_header(fp, std::string("Constrain for Timing/Power analysis on the mapped FPGA"));
|
||||
|
||||
/* Find the top_module */
|
||||
ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name());
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(top_module));
|
||||
|
||||
/* Create clock and set I/O ports with input/output delays */
|
||||
print_analysis_sdc_io_delays(fp,
|
||||
L_logical_blocks, device_size, L_grids, L_blocks,
|
||||
module_manager, top_module,
|
||||
circuit_lib, global_ports,
|
||||
critical_path_delay);
|
||||
|
||||
/* TODO: Disable the timing for global ports */
|
||||
/*
|
||||
verilog_generate_sdc_disable_global_ports(fp);
|
||||
*/
|
||||
|
||||
/* TODO: Disable the timing for configuration cells */
|
||||
/*
|
||||
verilog_generate_sdc_disable_sram_orgz(fp, cur_sram_orgz_info);
|
||||
*/
|
||||
|
||||
/* TODO: Disable timing for un-used resources */
|
||||
/* Apply to Routing Channels */
|
||||
/*
|
||||
if (TRUE == compact_routing_hierarchy) {
|
||||
verilog_generate_sdc_disable_unused_routing_channels(fp, LL_nx, LL_ny);
|
||||
} else {
|
||||
verilog_generate_sdc_disable_unused_routing_channels(fp, LL_nx, LL_ny,
|
||||
LL_num_rr_nodes, LL_rr_node,
|
||||
LL_rr_node_indices);
|
||||
}
|
||||
*/
|
||||
|
||||
/* TODO: Apply to Connection blocks */
|
||||
/*
|
||||
if (TRUE == compact_routing_hierarchy) {
|
||||
verilog_generate_sdc_disable_unused_cbs(fp, LL_nx, LL_ny, LL_device_rr_gsb);
|
||||
verilog_generate_sdc_disable_unused_cbs_muxs(fp, LL_nx, LL_ny, LL_device_rr_gsb);
|
||||
} else {
|
||||
verilog_generate_sdc_disable_unused_cbs(fp, LL_nx, LL_ny);
|
||||
verilog_generate_sdc_disable_unused_cbs_muxs(fp, LL_nx, LL_ny);
|
||||
}
|
||||
*/
|
||||
|
||||
/* TODO: Apply to Switch blocks */
|
||||
/*
|
||||
if (TRUE == compact_routing_hierarchy) {
|
||||
verilog_generate_sdc_disable_unused_sbs(fp);
|
||||
verilog_generate_sdc_disable_unused_sbs_muxs(fp);
|
||||
} else {
|
||||
verilog_generate_sdc_disable_unused_sbs(fp, LL_nx, LL_ny);
|
||||
verilog_generate_sdc_disable_unused_sbs_muxs(fp, LL_nx, LL_ny);
|
||||
}
|
||||
*/
|
||||
|
||||
/* TODO: Apply to Grids */
|
||||
/*
|
||||
verilog_generate_sdc_disable_unused_grids(fp, LL_nx, LL_ny, LL_grid, LL_block);
|
||||
verilog_generate_sdc_disable_unused_grids_muxs(fp, LL_nx, LL_ny, LL_grid, LL_block);
|
||||
*/
|
||||
|
||||
/* Close file handler */
|
||||
fp.close();
|
||||
|
||||
/* 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);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef ANALYSIS_SDC_WRITER_H
|
||||
#define ANALYSIS_SDC_WRITER_H
|
||||
|
||||
#include <string>
|
||||
#include "vpr_types.h"
|
||||
#include "rr_blocks.h"
|
||||
#include "module_manager.h"
|
||||
#include "bitstream_manager.h"
|
||||
|
||||
void print_analysis_sdc(const std::string& sdc_dir,
|
||||
const float& critical_path_delay,
|
||||
const DeviceRRGSB& L_device_rr_gsb,
|
||||
const std::vector<t_logical_block>& L_logical_blocks,
|
||||
const vtr::Point<size_t>& device_size,
|
||||
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
||||
const std::vector<t_block>& L_blocks,
|
||||
const ModuleManager& module_manager,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const std::vector<CircuitPortId>& global_ports,
|
||||
const bool& compact_routing_hierarchy);
|
||||
|
||||
#endif
|
|
@ -3,6 +3,7 @@
|
|||
*******************************************************************/
|
||||
#include <ctime>
|
||||
#include "pnr_sdc_writer.h"
|
||||
#include "analysis_sdc_writer.h"
|
||||
|
||||
#include "sdc_api.h"
|
||||
|
||||
|
@ -14,6 +15,10 @@ void fpga_sdc_generator(const SdcOption& sdc_options,
|
|||
const std::vector<std::vector<t_grid_tile>>& grids,
|
||||
const std::vector<t_switch_inf>& switches,
|
||||
const DeviceRRGSB& L_device_rr_gsb,
|
||||
const std::vector<t_logical_block>& L_logical_blocks,
|
||||
const vtr::Point<size_t>& device_size,
|
||||
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
||||
const std::vector<t_block>& L_blocks,
|
||||
const ModuleManager& module_manager,
|
||||
const MuxLibrary& mux_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
|
@ -33,6 +38,16 @@ void fpga_sdc_generator(const SdcOption& sdc_options,
|
|||
compact_routing_hierarchy);
|
||||
}
|
||||
|
||||
if (true == sdc_options.generate_sdc_analysis()) {
|
||||
print_analysis_sdc(sdc_options.sdc_dir(),
|
||||
critical_path_delay,
|
||||
L_device_rr_gsb,
|
||||
L_logical_blocks, device_size, L_grids, L_blocks,
|
||||
module_manager,
|
||||
circuit_lib, global_ports,
|
||||
compact_routing_hierarchy);
|
||||
}
|
||||
|
||||
/* End time count */
|
||||
clock_t t_end = clock();
|
||||
|
||||
|
|
|
@ -12,6 +12,10 @@ void fpga_sdc_generator(const SdcOption& sdc_options,
|
|||
const std::vector<std::vector<t_grid_tile>>& grids,
|
||||
const std::vector<t_switch_inf>& switches,
|
||||
const DeviceRRGSB& L_device_rr_gsb,
|
||||
const std::vector<t_logical_block>& L_logical_blocks,
|
||||
const vtr::Point<size_t>& device_size,
|
||||
const std::vector<std::vector<t_grid_tile>>& L_grids,
|
||||
const std::vector<t_block>& L_blocks,
|
||||
const ModuleManager& module_manager,
|
||||
const MuxLibrary& mux_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
|
|
|
@ -10,4 +10,6 @@ constexpr char* SDC_DISABLE_MUX_OUTPUTS_FILE_NAME = "disable_routing_multiplexer
|
|||
constexpr char* SDC_DISABLE_SB_OUTPUTS_FILE_NAME = "disable_sb_outputs.sdc";
|
||||
constexpr char* SDC_CB_FILE_NAME = "cb.sdc";
|
||||
|
||||
constexpr char* SDC_ANALYSIS_FILE_NAME = "fpga_top_analysis.sdc";
|
||||
|
||||
#endif
|
||||
|
|
|
@ -99,3 +99,74 @@ void print_pnr_sdc_constrain_module_port2port_timing(std::fstream& fp,
|
|||
tmax);
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Disable timing for a port
|
||||
*******************************************************************/
|
||||
void print_sdc_disable_port_timing(std::fstream& fp,
|
||||
const BasicPort& port) {
|
||||
/* Validate file stream */
|
||||
check_file_handler(fp);
|
||||
|
||||
fp << "set_disable_timing ";
|
||||
|
||||
fp << generate_sdc_port(port);
|
||||
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Set the input delay for a port in SDC format
|
||||
* Note that the input delay will be bounded by a clock port
|
||||
*******************************************************************/
|
||||
void print_sdc_set_port_input_delay(std::fstream& fp,
|
||||
const BasicPort& port,
|
||||
const BasicPort& clock_port,
|
||||
const float& delay) {
|
||||
/* Validate file stream */
|
||||
check_file_handler(fp);
|
||||
|
||||
fp << "set_input_delay ";
|
||||
|
||||
fp << "-clock ";
|
||||
|
||||
fp << generate_sdc_port(clock_port);
|
||||
|
||||
fp << " -max ";
|
||||
|
||||
fp << std::setprecision(10) << delay;
|
||||
|
||||
fp << " ";
|
||||
|
||||
fp << generate_sdc_port(port);
|
||||
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Set the output delay for a port in SDC format
|
||||
* Note that the output delay will be bounded by a clock port
|
||||
*******************************************************************/
|
||||
void print_sdc_set_port_output_delay(std::fstream& fp,
|
||||
const BasicPort& port,
|
||||
const BasicPort& clock_port,
|
||||
const float& delay) {
|
||||
/* Validate file stream */
|
||||
check_file_handler(fp);
|
||||
|
||||
fp << "set_output_delay ";
|
||||
|
||||
fp << "-clock ";
|
||||
|
||||
fp << generate_sdc_port(clock_port);
|
||||
|
||||
fp << " -max ";
|
||||
|
||||
fp << std::setprecision(10) << delay;
|
||||
|
||||
fp << " ";
|
||||
|
||||
fp << generate_sdc_port(port);
|
||||
|
||||
fp << std::endl;
|
||||
}
|
||||
|
|
|
@ -26,4 +26,17 @@ void print_pnr_sdc_constrain_module_port2port_timing(std::fstream& fp,
|
|||
const ModulePortId& module_output_port_id,
|
||||
const float& tmax);
|
||||
|
||||
void print_sdc_disable_port_timing(std::fstream& fp,
|
||||
const BasicPort& port);
|
||||
|
||||
void print_sdc_set_port_input_delay(std::fstream& fp,
|
||||
const BasicPort& port,
|
||||
const BasicPort& clock_port,
|
||||
const float& delay);
|
||||
|
||||
void print_sdc_set_port_output_delay(std::fstream& fp,
|
||||
const BasicPort& port,
|
||||
const BasicPort& clock_port,
|
||||
const float& delay);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -160,6 +160,7 @@ void vpr_fpga_x2p_tool_suites(t_vpr_setup vpr_setup,
|
|||
fpga_sdc_generator(sdc_options,
|
||||
Arch.spice->spice_params.stimulate_params.vpr_crit_path_delay / 1e-9,
|
||||
grids, rr_switches, device_rr_gsb,
|
||||
L_logical_blocks, device_size, grids, L_blocks,
|
||||
module_manager, mux_lib,
|
||||
Arch.spice->circuit_lib, global_ports,
|
||||
TRUE == vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy);
|
||||
|
|
Loading…
Reference in New Issue