bring pnr sdc generator online and fixed minor bugs in bitstream writing
This commit is contained in:
parent
e45fa18c4c
commit
092e10afda
|
@ -5,6 +5,9 @@
|
|||
#include "vtr_time.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
#include "build_device_bitstream.h"
|
||||
#include "bitstream_writer.h"
|
||||
#include "build_fabric_bitstream.h"
|
||||
|
@ -30,6 +33,11 @@ void fpga_bitstream(OpenfpgaContext& openfpga_ctx,
|
|||
cmd_context.option_enable(cmd, opt_verbose));
|
||||
|
||||
if (true == cmd_context.option_enable(cmd, opt_file)) {
|
||||
std::string src_dir_path = find_path_dir_name(cmd_context.option_value(cmd, opt_file));
|
||||
|
||||
/* Create directories */
|
||||
create_dir_path(src_dir_path.c_str());
|
||||
|
||||
write_arch_independent_bitstream_to_xml_file(openfpga_ctx.bitstream_manager(),
|
||||
cmd_context.option_value(cmd, opt_file));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/********************************************************************
|
||||
* 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 openfpgautil library */
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
#include "circuit_library_utils.h"
|
||||
#include "pnr_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
|
||||
*******************************************************************/
|
||||
void write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
|
||||
const Command& cmd, const CommandContext& cmd_context) {
|
||||
|
||||
CommandOptionId opt_output_dir = cmd.option("file");
|
||||
CommandOptionId opt_constrain_global_port = cmd.option("constrain_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");
|
||||
|
||||
/* 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_dir_path(sdc_dir_path.c_str());
|
||||
|
||||
PnrSdcOption options(sdc_dir_path);
|
||||
|
||||
options.set_constrain_global_port(cmd_context.option_enable(cmd, opt_constrain_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));
|
||||
|
||||
/* 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,
|
||||
0, /* TODO: add critical path stats to OpenFPGA context */
|
||||
//openfpga_ctx.vpr_timing_annotation().critical_path_delay();
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef OPENFPGA_SDC_H
|
||||
#define OPENFPGA_SDC_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "command.h"
|
||||
#include "command_context.h"
|
||||
#include "openfpga_context.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
void write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
|
||||
const Command& cmd, const CommandContext& cmd_context);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,79 @@
|
|||
/********************************************************************
|
||||
* Add commands to the OpenFPGA shell interface,
|
||||
* in purpose of generate SDC files
|
||||
* - write_pnr_sdc : generate SDC to constrain the back-end flow for FPGA fabric
|
||||
* - write_analysis_sdc: TODO: generate SDC based on users' implementations
|
||||
*******************************************************************/
|
||||
#include "openfpga_sdc.h"
|
||||
#include "openfpga_sdc_command.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* - Add a command to Shell environment: generate PnR SDC
|
||||
* - Add associated options
|
||||
* - Add command dependency
|
||||
*******************************************************************/
|
||||
static
|
||||
void add_openfpga_write_pnr_sdc_command(openfpga::Shell<OpenfpgaContext>& shell,
|
||||
const ShellCommandClassId& cmd_class_id,
|
||||
const ShellCommandId& shell_cmd_build_fabric_id) {
|
||||
Command shell_cmd("write_pnr_sdc");
|
||||
|
||||
/* Add an option '--file' in short '-f'*/
|
||||
CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for SDC files");
|
||||
shell_cmd.set_option_short_name(output_opt, "f");
|
||||
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);
|
||||
|
||||
/* Add an option '--constrain_global_port' */
|
||||
shell_cmd.add_option("constrain_global_port", false, "Constrain all the global ports of FPGA fabric");
|
||||
|
||||
/* Add an option '--constrain_grid' */
|
||||
shell_cmd.add_option("constrain_grid", false, "Constrain all the grids of FPGA fabric");
|
||||
|
||||
/* Add an option '--constrain_sb' */
|
||||
shell_cmd.add_option("constrain_sb", false, "Constrain all the switch blocks of FPGA fabric");
|
||||
|
||||
/* Add an option '--constrain_cb' */
|
||||
shell_cmd.add_option("constrain_cb", false, "Constrain all the connection blocks of FPGA fabric");
|
||||
|
||||
/* Add an option '--constrain_configurable_memory_outputs' */
|
||||
shell_cmd.add_option("constrain_configurable_memory_outputs", false, "Constrain all the outputs of configurable memories of FPGA fabric");
|
||||
|
||||
/* Add an option '--constrain_routing_multiplexer_outputs' */
|
||||
shell_cmd.add_option("constrain_routing_multiplexer_outputs", false, "Constrain all the outputs of routing multiplexer of FPGA fabric");
|
||||
|
||||
/* Add an option '--constrain_switch_block_outputs' */
|
||||
shell_cmd.add_option("constrain_switch_block_outputs", false, "Constrain all the outputs of switch blocks of FPGA fabric");
|
||||
|
||||
/* Add an option '--verbose' */
|
||||
shell_cmd.add_option("verbose", false, "Enable verbose output");
|
||||
|
||||
/* Add command 'write_fabric_verilog' to the Shell */
|
||||
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate SDC files to constrain the backend flow for FPGA fabric");
|
||||
shell.set_command_class(shell_cmd_id, cmd_class_id);
|
||||
shell.set_command_execute_function(shell_cmd_id, write_pnr_sdc);
|
||||
|
||||
/* The 'build_fabric' command should NOT be executed before 'link_openfpga_arch' */
|
||||
std::vector<ShellCommandId> cmd_dependency;
|
||||
cmd_dependency.push_back(shell_cmd_build_fabric_id);
|
||||
shell.set_command_dependency(shell_cmd_id, cmd_dependency);
|
||||
}
|
||||
|
||||
void add_openfpga_sdc_commands(openfpga::Shell<OpenfpgaContext>& shell) {
|
||||
/* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */
|
||||
const ShellCommandId& shell_cmd_build_fabric_id = shell.command(std::string("build_fabric"));
|
||||
|
||||
/* Add a new class of commands */
|
||||
ShellCommandClassId openfpga_sdc_cmd_class = shell.add_command_class("FPGA-SDC");
|
||||
|
||||
/********************************
|
||||
* Command 'write_fabric_verilog'
|
||||
*/
|
||||
add_openfpga_write_pnr_sdc_command(shell,
|
||||
openfpga_sdc_cmd_class,
|
||||
shell_cmd_build_fabric_id);
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef OPENFPGA_SDC_COMMAND_H
|
||||
#define OPENFPGA_SDC_COMMAND_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include "shell.h"
|
||||
#include "openfpga_context.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
void add_openfpga_sdc_commands(openfpga::Shell<OpenfpgaContext>& shell);
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
|
@ -323,7 +323,7 @@ void print_pnr_sdc_constrain_grid_timing(const std::string& sdc_dir,
|
|||
const ModuleManager& module_manager) {
|
||||
|
||||
/* Start time count */
|
||||
vtr::ScopedStartFinishTimer timer("Generating SDC for constraining grid timing for P&R flow");
|
||||
vtr::ScopedStartFinishTimer timer("Write SDC for constraining grid timing for P&R flow");
|
||||
|
||||
for (const t_physical_tile_type& physical_tile : device_ctx.physical_tile_types) {
|
||||
/* Bypass empty type or nullptr */
|
||||
|
|
|
@ -166,7 +166,7 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_di
|
|||
const DeviceRRGSB& device_rr_gsb) {
|
||||
|
||||
/* Start time count */
|
||||
vtr::ScopedStartFinishTimer timer("Generating SDC for constrain Switch Block timing for P&R flow");
|
||||
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Switch Block timing for P&R flow");
|
||||
|
||||
/* Get the range of SB array */
|
||||
vtr::Point<size_t> sb_range = device_rr_gsb.get_gsb_range();
|
||||
|
@ -195,7 +195,7 @@ void print_pnr_sdc_compact_routing_constrain_sb_timing(const std::string& sdc_di
|
|||
const DeviceRRGSB& device_rr_gsb) {
|
||||
|
||||
/* Start time count */
|
||||
vtr::ScopedStartFinishTimer timer("Generating SDC for constrain Switch Block timing for P&R flow");
|
||||
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Switch Block timing for P&R flow");
|
||||
|
||||
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);
|
||||
|
@ -362,7 +362,7 @@ void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_di
|
|||
const DeviceRRGSB& device_rr_gsb) {
|
||||
|
||||
/* Start time count */
|
||||
vtr::ScopedStartFinishTimer timer("Generating SDC for constrain Connection Block timing for P&R flow");
|
||||
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Connection Block timing for P&R flow");
|
||||
|
||||
print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_dir, module_manager,
|
||||
rr_graph,
|
||||
|
@ -385,7 +385,7 @@ void print_pnr_sdc_compact_routing_constrain_cb_timing(const std::string& sdc_di
|
|||
const DeviceRRGSB& device_rr_gsb) {
|
||||
|
||||
/* Start time count */
|
||||
vtr::ScopedStartFinishTimer timer("Generating SDC for constrain Connection Block timing for P&R flow");
|
||||
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Connection Block timing for P&R flow");
|
||||
|
||||
/* Print SDC for unique X-direction connection block modules */
|
||||
for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(CHANX); ++icb) {
|
||||
|
|
|
@ -58,7 +58,7 @@ void print_pnr_sdc_global_ports(const std::string& sdc_dir,
|
|||
std::string sdc_fname(sdc_dir + std::string(SDC_GLOBAL_PORTS_FILE_NAME));
|
||||
|
||||
/* Start time count */
|
||||
std::string timer_message = std::string("Generating SDC for constraining clocks for P&R flow '") + sdc_fname + std::string("'");
|
||||
std::string timer_message = std::string("Write SDC for constraining clocks for P&R flow '") + sdc_fname + std::string("'");
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Create the file stream */
|
||||
|
@ -153,7 +153,7 @@ void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_
|
|||
std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_CONFIG_MEM_OUTPUTS_FILE_NAME));
|
||||
|
||||
/* Start time count */
|
||||
std::string timer_message = std::string("Generating SDC to disable configurable memory outputs for P&R flow '") + sdc_fname + std::string("'");
|
||||
std::string timer_message = std::string("Write SDC to disable configurable memory outputs for P&R flow '") + sdc_fname + std::string("'");
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Create the file stream */
|
||||
|
@ -187,7 +187,7 @@ void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir,
|
|||
std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_MUX_OUTPUTS_FILE_NAME));
|
||||
|
||||
/* Start time count */
|
||||
std::string timer_message = std::string("Generating SDC to disable routing multiplexer outputs for P&R flow '") + sdc_fname + std::string("'");
|
||||
std::string timer_message = std::string("Write SDC to disable routing multiplexer outputs for P&R flow '") + sdc_fname + std::string("'");
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Create the file stream */
|
||||
|
@ -242,7 +242,7 @@ void print_pnr_sdc_flatten_routing_disable_switch_block_outputs(const std::strin
|
|||
std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_SB_OUTPUTS_FILE_NAME));
|
||||
|
||||
/* Start time count */
|
||||
std::string timer_message = std::string("Generating SDC to disable switch block outputs for P&R flow '") + sdc_fname + std::string("'");
|
||||
std::string timer_message = std::string("Write SDC to disable switch block outputs for P&R flow '") + sdc_fname + std::string("'");
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Create the file stream */
|
||||
|
@ -298,7 +298,7 @@ void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::strin
|
|||
std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_SB_OUTPUTS_FILE_NAME));
|
||||
|
||||
/* Start time count */
|
||||
std::string timer_message = std::string("Generating SDC to disable switch block outputs for P&R flow '") + sdc_fname + std::string("'");
|
||||
std::string timer_message = std::string("Write SDC to disable switch block outputs for P&R flow '") + sdc_fname + std::string("'");
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Create the file stream */
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "openfpga_setup_command.h"
|
||||
#include "openfpga_verilog_command.h"
|
||||
#include "openfpga_bitstream_command.h"
|
||||
#include "openfpga_sdc_command.h"
|
||||
#include "basic_command.h"
|
||||
|
||||
#include "openfpga_title.h"
|
||||
|
@ -60,6 +61,9 @@ int main(int argc, char** argv) {
|
|||
/* Add openfpga bitstream commands */
|
||||
openfpga::add_openfpga_bitstream_commands(shell);
|
||||
|
||||
/* Add openfpga sdc commands */
|
||||
openfpga::add_openfpga_sdc_commands(shell);
|
||||
|
||||
/* Add basic commands: exit, help, etc.
|
||||
* Note:
|
||||
* This MUST be the last command group to be added!
|
||||
|
|
|
@ -35,10 +35,19 @@ fpga_bitstream --verbose --file /var/tmp/xtang/openfpga_test_src/fabric_indepene
|
|||
|
||||
# Write the Verilog netlist for FPGA fabric
|
||||
# - Enable the use of explicit port mapping in Verilog netlist
|
||||
write_fabric_verilog --file /var/tmp/xtang/openfpga_test_src --explicit_port_mapping --include_timing --include_signal_init --support_icarus_simulator --print_user_defined_template --verbose
|
||||
write_fabric_verilog --file /var/tmp/xtang/openfpga_test_src/SRC --explicit_port_mapping --include_timing --include_signal_init --support_icarus_simulator --print_user_defined_template --verbose
|
||||
|
||||
# Write the Verilog testbench for FPGA fabric
|
||||
write_verilog_testbench --file /var/tmp/xtang/openfpga_test_src --reference_benchmark_file_path /var/tmp/xtang/s298.v --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini /var/tmp/xtang/openfpga_test_src/simulation_deck.ini
|
||||
# - We suggest the use of same output directory as fabric Verilog netlists
|
||||
# - Must specify the reference benchmark file if you want to output any testbenches
|
||||
# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA
|
||||
# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase
|
||||
# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts
|
||||
write_verilog_testbench --file /var/tmp/xtang/openfpga_test_src/SRC --reference_benchmark_file_path /var/tmp/xtang/s298.v --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini /var/tmp/xtang/openfpga_test_src/simulation_deck.ini
|
||||
|
||||
# Write the SDC files for PnR backend
|
||||
# - Turn on every options here
|
||||
write_pnr_sdc --file /var/tmp/xtang/openfpga_test_src/SDC
|
||||
|
||||
# Finish and exit OpenFPGA
|
||||
exit
|
||||
|
|
Loading…
Reference in New Issue