add options to dsiable SDC for non-clock global ports

This commit is contained in:
tangxifan 2020-03-25 14:38:13 -06:00
parent 787dc8ce83
commit c2e5d6b8e2
7 changed files with 239 additions and 100 deletions

View File

@ -27,6 +27,7 @@ void write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
CommandOptionId opt_output_dir = cmd.option("file"); CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_constrain_global_port = cmd.option("constrain_global_port"); 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_grid = cmd.option("constrain_grid");
CommandOptionId opt_constrain_sb = cmd.option("constrain_sb"); CommandOptionId opt_constrain_sb = cmd.option("constrain_sb");
CommandOptionId opt_constrain_cb = cmd.option("constrain_cb"); CommandOptionId opt_constrain_cb = cmd.option("constrain_cb");
@ -45,6 +46,7 @@ void write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
PnrSdcOption options(sdc_dir_path); PnrSdcOption options(sdc_dir_path);
options.set_constrain_global_port(cmd_context.option_enable(cmd, opt_constrain_global_port)); 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_grid(cmd_context.option_enable(cmd, opt_constrain_grid));
options.set_constrain_sb(cmd_context.option_enable(cmd, opt_constrain_sb)); 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_cb(cmd_context.option_enable(cmd, opt_constrain_cb));

View File

@ -29,6 +29,9 @@ ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shell<OpenfpgaContex
/* Add an option '--constrain_global_port' */ /* Add an option '--constrain_global_port' */
shell_cmd.add_option("constrain_global_port", false, "Constrain all the global ports of FPGA fabric"); shell_cmd.add_option("constrain_global_port", false, "Constrain all the global ports of FPGA fabric");
/* Add an option '--constrain_non_clock_global_port' */
shell_cmd.add_option("constrain_non_clock_global_port", false, "Constrain all the non-clock global ports as clock ports of FPGA fabric");
/* Add an option '--constrain_grid' */ /* Add an option '--constrain_grid' */
shell_cmd.add_option("constrain_grid", false, "Constrain all the grids of FPGA fabric"); shell_cmd.add_option("constrain_grid", false, "Constrain all the grids of FPGA fabric");

View File

@ -0,0 +1,192 @@
/********************************************************************
* This file includes functions that print SDC (Synopsys Design Constraint)
* files in physical design tools, i.e., Place & Route (PnR) tools
* The SDC files are used to constrain global ports for each module
* in FPGA fabric, such as Configurable Logic Blocks (CLBs),
* Heterogeneous blocks, Switch Blocks (SBs) and Connection Blocks (CBs)
*
* Note that this is different from the SDC to constrain VPR Place&Route
* engine! These SDCs are designed for PnR to generate FPGA layouts!!!
*******************************************************************/
#include <ctime>
#include <fstream>
#include <iomanip>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_time.h"
#include "vtr_log.h"
/* Headers from openfpgautil library */
#include "openfpga_port.h"
#include "openfpga_digest.h"
#include "sdc_writer_naming.h"
#include "sdc_writer_utils.h"
#include "pnr_sdc_global_port.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Print SDC constraint for a clock port
* This format is derived from the open-source SDC syntax,
* which is supposed to be generic
*
* This function is design to the SDC writer for any port
* wants to be treated as a clock port
*******************************************************************/
static
void print_pnr_sdc_clock_port(std::fstream& fp,
const BasicPort& port_to_constrain,
const float& clock_period) {
valid_file_stream(fp);
fp << "create_clock";
fp << " -name " << generate_sdc_port(port_to_constrain);
fp << " -period " << std::setprecision(10) << clock_period;
fp << " -waveform {0 " << std::setprecision(10) << clock_period / 2 << "}";
fp << " [get_ports{" << generate_sdc_port(port_to_constrain) << "}]";
fp << std::endl;
}
/********************************************************************
* Print SDC constraints for the clock ports which are the global ports
* of FPGA fabric
*
* For programming clock, we give a fixed period, while for operating
* clock, we constrain with critical path delay
*******************************************************************/
static
void print_pnr_sdc_global_clock_ports(std::fstream& fp,
const float& programming_critical_path_delay,
const float& operating_critical_path_delay,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports) {
valid_file_stream(fp);
/* Get clock port from the global port */
for (const CircuitPortId& clock_port : global_ports) {
if (CIRCUIT_MODEL_PORT_CLOCK != circuit_lib.port_type(clock_port)) {
continue;
}
/* Reach here, it means a clock port and we need print constraints */
float clock_period = operating_critical_path_delay;
/* For programming clock, we give a fixed period */
if (true == circuit_lib.port_is_prog(clock_port)) {
clock_period = programming_critical_path_delay;
/* Print comments */
fp << "##################################################" << std::endl;
fp << "# Create programmable clock " << std::endl;
fp << "##################################################" << std::endl;
} else {
/* Print comments */
fp << "##################################################" << std::endl;
fp << "# Create clock " << std::endl;
fp << "##################################################" << std::endl;
}
for (const size_t& pin : circuit_lib.pins(clock_port)) {
BasicPort port_to_constrain(circuit_lib.port_prefix(clock_port), pin, pin);
print_pnr_sdc_clock_port(fp,
port_to_constrain,
clock_period);
}
}
}
/********************************************************************
* Print SDC constraints for the non-clock ports which are the global ports
* of FPGA fabric
* Here, we will the treat the non-clock ports as the clock ports
* in the CTS
* Note that, this may be applied to the reset, set and other global
* signals which do need very balanced delays to each sink
*******************************************************************/
static
void print_pnr_sdc_global_non_clock_ports(std::fstream& fp,
const float& operating_critical_path_delay,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports) {
valid_file_stream(fp);
/* For non-clock port from the global port: give a fixed period */
for (const CircuitPortId& global_port : global_ports) {
if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(global_port)) {
continue;
}
/* Print comments */
fp << "##################################################" << std::endl;
fp << "# Constrain other global ports " << std::endl;
fp << "##################################################" << std::endl;
/* Reach here, it means a non-clock global port and we need print constraints */
float clock_period = operating_critical_path_delay;
for (const size_t& pin : circuit_lib.pins(global_port)) {
BasicPort port_to_constrain(circuit_lib.port_prefix(global_port), pin, pin);
print_pnr_sdc_clock_port(fp,
port_to_constrain,
clock_period);
}
}
}
/********************************************************************
* Print a SDC file to constrain the global ports of FPGA fabric
* in particular clock ports
*
* This ports to appear in this file will be treated in Clock Tree
* Synthesis (CTS)
*
* For non-clock global ports, we have an option to select if they
* should be treated in CTS or not
* In general, we do not recommend to do this
*******************************************************************/
void print_pnr_sdc_global_ports(const std::string& sdc_dir,
const float& programming_critical_path_delay,
const float& operating_critical_path_delay,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports,
const bool& constrain_non_clock_port) {
/* Create the file name for Verilog netlist */
std::string sdc_fname(sdc_dir + std::string(SDC_GLOBAL_PORTS_FILE_NAME));
/* Start time count */
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 */
std::fstream fp;
fp.open(sdc_fname, std::fstream::out | std::fstream::trunc);
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Clock contraints for PnR"));
print_pnr_sdc_global_clock_ports(fp,
programming_critical_path_delay,
operating_critical_path_delay,
circuit_lib,
global_ports);
if (true == constrain_non_clock_port) {
print_pnr_sdc_global_non_clock_ports(fp,
operating_critical_path_delay,
circuit_lib,
global_ports);
}
/* Close file handler */
fp.close();
}
} /* end namespace openfpga */

View File

@ -0,0 +1,27 @@
#ifndef PNR_SDC_GLBOAL_PORT_H
#define PNR_SDC_GLBOAL_PORT_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include <vector>
#include "circuit_library.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
void print_pnr_sdc_global_ports(const std::string& sdc_dir,
const float& programming_critical_path_delay,
const float& operating_critical_path_delay,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports,
const bool& constrain_non_clock_port);
} /* end namespace openfpga */
#endif

View File

@ -12,6 +12,7 @@ namespace openfpga {
PnrSdcOption::PnrSdcOption(const std::string& sdc_dir) { PnrSdcOption::PnrSdcOption(const std::string& sdc_dir) {
sdc_dir_ = sdc_dir; sdc_dir_ = sdc_dir;
constrain_global_port_ = false; constrain_global_port_ = false;
constrain_non_clock_global_port_ = false;
constrain_grid_ = false; constrain_grid_ = false;
constrain_sb_ = false; constrain_sb_ = false;
constrain_cb_ = false; constrain_cb_ = false;
@ -41,6 +42,10 @@ bool PnrSdcOption::constrain_global_port() const {
return constrain_global_port_; return constrain_global_port_;
} }
bool PnrSdcOption::constrain_non_clock_global_port() const {
return constrain_non_clock_global_port_;
}
bool PnrSdcOption::constrain_grid() const { bool PnrSdcOption::constrain_grid() const {
return constrain_grid_; return constrain_grid_;
} }
@ -86,6 +91,10 @@ void PnrSdcOption::set_constrain_global_port(const bool& constrain_global_port)
constrain_global_port_ = constrain_global_port; constrain_global_port_ = constrain_global_port;
} }
void PnrSdcOption::set_constrain_non_clock_global_port(const bool& constrain_non_clock_global_port) {
constrain_non_clock_global_port_ = constrain_non_clock_global_port;
}
void PnrSdcOption::set_constrain_grid(const bool& constrain_grid) { void PnrSdcOption::set_constrain_grid(const bool& constrain_grid) {
constrain_grid_ = constrain_grid; constrain_grid_ = constrain_grid;
} }

View File

@ -18,6 +18,7 @@ class PnrSdcOption {
std::string sdc_dir() const; std::string sdc_dir() const;
bool generate_sdc_pnr() const; bool generate_sdc_pnr() const;
bool constrain_global_port() const; bool constrain_global_port() const;
bool constrain_non_clock_global_port() const;
bool constrain_grid() const; bool constrain_grid() const;
bool constrain_sb() const; bool constrain_sb() const;
bool constrain_cb() const; bool constrain_cb() const;
@ -28,6 +29,7 @@ class PnrSdcOption {
void set_sdc_dir(const std::string& sdc_dir); void set_sdc_dir(const std::string& sdc_dir);
void set_generate_sdc_pnr(const bool& generate_sdc_pnr); void set_generate_sdc_pnr(const bool& generate_sdc_pnr);
void set_constrain_global_port(const bool& constrain_global_port); void set_constrain_global_port(const bool& constrain_global_port);
void set_constrain_non_clock_global_port(const bool& constrain_non_clock_global_port);
void set_constrain_grid(const bool& constrain_grid); void set_constrain_grid(const bool& constrain_grid);
void set_constrain_sb(const bool& constrain_sb); void set_constrain_sb(const bool& constrain_sb);
void set_constrain_cb(const bool& constrain_cb); void set_constrain_cb(const bool& constrain_cb);
@ -37,6 +39,7 @@ class PnrSdcOption {
private: /* Internal data */ private: /* Internal data */
std::string sdc_dir_; std::string sdc_dir_;
bool constrain_global_port_; bool constrain_global_port_;
bool constrain_non_clock_global_port_;
bool constrain_grid_; bool constrain_grid_;
bool constrain_sb_; bool constrain_sb_;
bool constrain_cb_; bool constrain_cb_;

View File

@ -28,6 +28,7 @@
#include "sdc_writer_naming.h" #include "sdc_writer_naming.h"
#include "sdc_writer_utils.h" #include "sdc_writer_utils.h"
#include "sdc_memory_utils.h" #include "sdc_memory_utils.h"
#include "pnr_sdc_global_port.h"
#include "pnr_sdc_routing_writer.h" #include "pnr_sdc_routing_writer.h"
#include "pnr_sdc_grid_writer.h" #include "pnr_sdc_grid_writer.h"
#include "pnr_sdc_writer.h" #include "pnr_sdc_writer.h"
@ -35,105 +36,6 @@
/* begin namespace openfpga */ /* begin namespace openfpga */
namespace openfpga { namespace openfpga {
/********************************************************************
* Print a SDC file to constrain the global ports of FPGA fabric
* in particular clock ports
*
* For programming clock, we give a fixed period, while for operating
* clock, we constrain with critical path delay
*******************************************************************/
static
void print_pnr_sdc_global_ports(const std::string& sdc_dir,
const float& programming_critical_path_delay,
const float& operating_critical_path_delay,
const CircuitLibrary& circuit_lib,
const std::vector<CircuitPortId>& global_ports) {
/* Create the file name for Verilog netlist */
std::string sdc_fname(sdc_dir + std::string(SDC_GLOBAL_PORTS_FILE_NAME));
/* Start time count */
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 */
std::fstream fp;
fp.open(sdc_fname, std::fstream::out | std::fstream::trunc);
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Clock contraints for PnR"));
/* Get clock port from the global port */
for (const CircuitPortId& clock_port : global_ports) {
if (CIRCUIT_MODEL_PORT_CLOCK != circuit_lib.port_type(clock_port)) {
continue;
}
/* Reach here, it means a clock port and we need print constraints */
float clock_period = operating_critical_path_delay;
/* For programming clock, we give a fixed period */
if (true == circuit_lib.port_is_prog(clock_port)) {
clock_period = programming_critical_path_delay;
/* Print comments */
fp << "##################################################" << std::endl;
fp << "# Create programmable clock " << std::endl;
fp << "##################################################" << std::endl;
} else {
/* Print comments */
fp << "##################################################" << std::endl;
fp << "# Create clock " << std::endl;
fp << "##################################################" << std::endl;
}
for (const size_t& pin : circuit_lib.pins(clock_port)) {
BasicPort port_to_constrain(circuit_lib.port_prefix(clock_port), pin, pin);
fp << "create_clock ";
fp << generate_sdc_port(port_to_constrain) << "-period ";
fp << std::setprecision(10) << clock_period;
fp << " -waveform {0 ";
fp << std::setprecision(10) << clock_period / 2;
fp << "}" << std::endl;
fp << std::endl;
}
}
/* For non-clock port from the global port: give a fixed period */
for (const CircuitPortId& global_port : global_ports) {
if (CIRCUIT_MODEL_PORT_CLOCK == circuit_lib.port_type(global_port)) {
continue;
}
/* Print comments */
fp << "##################################################" << std::endl;
fp << "# Constrain other global ports " << std::endl;
fp << "##################################################" << std::endl;
/* Reach here, it means a non-clock global port and we need print constraints */
float clock_period = operating_critical_path_delay;
for (const size_t& pin : circuit_lib.pins(global_port)) {
BasicPort port_to_constrain(circuit_lib.port_prefix(global_port), pin, pin);
fp << "create_clock ";
fp << generate_sdc_port(port_to_constrain) << "-period ";
fp << std::setprecision(10) << clock_period;
fp << " -waveform {0 ";
fp << std::setprecision(10) << clock_period / 2;
fp << "} ";
fp << "[list [get_ports { " << generate_sdc_port(port_to_constrain) << "}]]" << std::endl;
fp << "set_drive 0 " << generate_sdc_port(port_to_constrain) << std::endl;
fp << std::endl;
}
}
/* Close file handler */
fp.close();
}
/******************************************************************** /********************************************************************
* Break combinational loops in FPGA fabric, which mainly come from * Break combinational loops in FPGA fabric, which mainly come from
* configurable memory cells. * configurable memory cells.
@ -354,7 +256,8 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
print_pnr_sdc_global_ports(sdc_options.sdc_dir(), print_pnr_sdc_global_ports(sdc_options.sdc_dir(),
programming_critical_path_delay, programming_critical_path_delay,
operating_critical_path_delay, operating_critical_path_delay,
circuit_lib, global_ports); circuit_lib, global_ports,
sdc_options.constrain_non_clock_global_port());
} }
std::string top_module_name = generate_fpga_top_module_name(); std::string top_module_name = generate_fpga_top_module_name();