OpenFPGA/openfpga/src/base/openfpga_sdc.cpp

215 lines
10 KiB
C++

/********************************************************************
* This file includes functions to compress the hierachy of routing architecture
*******************************************************************/
/* Headers from vtrutil library */
#include "vtr_time.h"
#include "vtr_log.h"
/* Headers from openfpgashell library */
#include "command_exit_codes.h"
/* Headers from openfpgautil library */
#include "openfpga_scale.h"
#include "openfpga_digest.h"
#include "circuit_library_utils.h"
#include "pnr_sdc_writer.h"
#include "analysis_sdc_writer.h"
#include "configuration_chain_sdc_writer.h"
#include "configure_port_sdc_writer.h"
#include "openfpga_sdc.h"
/* Include global variables of VPR */
#include "globals.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* A wrapper function to call the PnR SDC generator of FPGA-SDC
*******************************************************************/
int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
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");
CommandOptionId opt_constrain_sb = cmd.option("constrain_sb");
CommandOptionId opt_constrain_cb = cmd.option("constrain_cb");
CommandOptionId opt_constrain_configurable_memory_outputs = cmd.option("constrain_configurable_memory_outputs");
CommandOptionId opt_constrain_routing_multiplexer_outputs = cmd.option("constrain_routing_multiplexer_outputs");
CommandOptionId opt_constrain_switch_block_outputs = cmd.option("constrain_switch_block_outputs");
CommandOptionId opt_constrain_zero_delay_paths = cmd.option("constrain_zero_delay_paths");
/* This is an intermediate data structure which is designed to modularize the FPGA-SDC
* Keep it independent from any other outside data structures
*/
std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir));
/* Create directories */
create_directory(sdc_dir_path);
PnrSdcOption options(sdc_dir_path);
options.set_flatten_names(cmd_context.option_enable(cmd, opt_flatten_names));
options.set_hierarchical(cmd_context.option_enable(cmd, opt_hierarchical));
if (true == cmd_context.option_enable(cmd, opt_time_unit)) {
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));
options.set_constrain_sb(cmd_context.option_enable(cmd, opt_constrain_sb));
options.set_constrain_cb(cmd_context.option_enable(cmd, opt_constrain_cb));
options.set_constrain_configurable_memory_outputs(cmd_context.option_enable(cmd, opt_constrain_configurable_memory_outputs));
options.set_constrain_routing_multiplexer_outputs(cmd_context.option_enable(cmd, opt_constrain_routing_multiplexer_outputs));
options.set_constrain_switch_block_outputs(cmd_context.option_enable(cmd, opt_constrain_switch_block_outputs));
options.set_constrain_zero_delay_paths(cmd_context.option_enable(cmd, opt_constrain_zero_delay_paths));
/* We first turn on default sdc option and then disable part of them by following users' options */
if (false == options.generate_sdc_pnr()) {
options.set_generate_sdc_pnr(true);
}
/* Collect global ports from the circuit library:
* TODO: should we place this in the OpenFPGA context?
*/
std::vector<CircuitPortId> global_ports = find_circuit_library_global_ports(openfpga_ctx.arch().circuit_lib);
/* Execute only when sdc is enabled */
if (true == options.generate_sdc_pnr()) {
print_pnr_sdc(options,
1./openfpga_ctx.simulation_setting().programming_clock_frequency(),
1./openfpga_ctx.simulation_setting().operating_clock_frequency(),
g_vpr_ctx.device(),
openfpga_ctx.vpr_device_annotation(),
openfpga_ctx.device_rr_gsb(),
openfpga_ctx.module_graph(),
openfpga_ctx.mux_lib(),
openfpga_ctx.arch().circuit_lib,
global_ports,
openfpga_ctx.flow_manager().compress_routing());
}
/* TODO: should identify the error code from internal function execution */
return CMD_EXEC_SUCCESS;
}
/********************************************************************
* A wrapper function to call the PnR SDC generator on configuration chain
* of FPGA-SDC
*******************************************************************/
int write_configuration_chain_sdc(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
/* If the configuration protocol is not a configuration chain, we will not write anything */
if (CONFIG_MEM_SCAN_CHAIN != openfpga_ctx.arch().config_protocol.type()) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Configuration protocol is %s. Expected %s to write SDC!\n",
CONFIG_PROTOCOL_TYPE_STRING[openfpga_ctx.arch().config_protocol.type()],
CONFIG_PROTOCOL_TYPE_STRING[CONFIG_MEM_SCAN_CHAIN]);
return CMD_EXEC_FATAL_ERROR;
}
/* Get command options */
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_time_unit = cmd.option("time_unit");
CommandOptionId opt_min_delay = cmd.option("min_delay");
CommandOptionId opt_max_delay = cmd.option("max_delay");
std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir));
float time_unit = string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit));
/* Write the SDC for configuration chain */
print_pnr_sdc_constrain_configurable_chain(cmd_context.option_value(cmd, opt_output_dir),
time_unit,
std::stof(cmd_context.option_value(cmd, opt_max_delay)),
std::stof(cmd_context.option_value(cmd, opt_min_delay)),
openfpga_ctx.module_graph());
return CMD_EXEC_SUCCESS;
}
/********************************************************************
* A wrapper function to call the PnR SDC generator on routing multiplexers
* of FPGA-SDC
*******************************************************************/
int write_sdc_disable_timing_configure_ports(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
/* Get command options */
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_flatten_names = cmd.option("flatten_names");
CommandOptionId opt_verbose = cmd.option("verbose");
std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir));
/* Write the SDC for configuration chain */
if (CMD_EXEC_FATAL_ERROR ==
print_sdc_disable_timing_configure_ports(cmd_context.option_value(cmd, opt_output_dir),
cmd_context.option_enable(cmd, opt_flatten_names),
openfpga_ctx.mux_lib(),
openfpga_ctx.arch().circuit_lib,
openfpga_ctx.module_graph(),
cmd_context.option_enable(cmd, opt_verbose))) {
return CMD_EXEC_FATAL_ERROR;
}
return CMD_EXEC_SUCCESS;
}
/********************************************************************
* A wrapper function to call the analysis SDC generator of FPGA-SDC
*******************************************************************/
int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_flatten_names = cmd.option("flatten_names");
CommandOptionId opt_time_unit = cmd.option("time_unit");
/* This is an intermediate data structure which is designed to modularize the FPGA-SDC
* Keep it independent from any other outside data structures
*/
std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir));
/* Create directories */
create_directory(sdc_dir_path);
AnalysisSdcOption options(sdc_dir_path);
options.set_generate_sdc_analysis(true);
options.set_flatten_names(cmd_context.option_enable(cmd, opt_flatten_names));
if (true == cmd_context.option_enable(cmd, opt_time_unit)) {
options.set_time_unit(string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit)));
}
/* Collect global ports from the circuit library:
* TODO: should we place this in the OpenFPGA context?
*/
std::vector<CircuitPortId> global_ports = find_circuit_library_global_ports(openfpga_ctx.arch().circuit_lib);
if (true == options.generate_sdc_analysis()) {
print_analysis_sdc(options,
1./openfpga_ctx.simulation_setting().operating_clock_frequency(),
g_vpr_ctx,
openfpga_ctx,
global_ports,
openfpga_ctx.flow_manager().compress_routing());
}
/* TODO: should identify the error code from internal function execution */
return CMD_EXEC_SUCCESS;
}
} /* end namespace openfpga */