add options to dsiable SDC for non-clock global ports
This commit is contained in:
parent
787dc8ce83
commit
c2e5d6b8e2
|
@ -27,6 +27,7 @@ void write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
|
|||
|
||||
CommandOptionId opt_output_dir = cmd.option("file");
|
||||
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");
|
||||
|
@ -45,6 +46,7 @@ void write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
|
|||
PnrSdcOption options(sdc_dir_path);
|
||||
|
||||
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));
|
||||
|
|
|
@ -29,6 +29,9 @@ ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shell<OpenfpgaContex
|
|||
/* 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_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' */
|
||||
shell_cmd.add_option("constrain_grid", false, "Constrain all the grids of FPGA fabric");
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
|
@ -12,6 +12,7 @@ namespace openfpga {
|
|||
PnrSdcOption::PnrSdcOption(const std::string& sdc_dir) {
|
||||
sdc_dir_ = sdc_dir;
|
||||
constrain_global_port_ = false;
|
||||
constrain_non_clock_global_port_ = false;
|
||||
constrain_grid_ = false;
|
||||
constrain_sb_ = false;
|
||||
constrain_cb_ = false;
|
||||
|
@ -41,6 +42,10 @@ bool PnrSdcOption::constrain_global_port() const {
|
|||
return constrain_global_port_;
|
||||
}
|
||||
|
||||
bool PnrSdcOption::constrain_non_clock_global_port() const {
|
||||
return constrain_non_clock_global_port_;
|
||||
}
|
||||
|
||||
bool PnrSdcOption::constrain_grid() const {
|
||||
return constrain_grid_;
|
||||
}
|
||||
|
@ -86,6 +91,10 @@ void PnrSdcOption::set_constrain_global_port(const bool& 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) {
|
||||
constrain_grid_ = constrain_grid;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ class PnrSdcOption {
|
|||
std::string sdc_dir() const;
|
||||
bool generate_sdc_pnr() const;
|
||||
bool constrain_global_port() const;
|
||||
bool constrain_non_clock_global_port() const;
|
||||
bool constrain_grid() const;
|
||||
bool constrain_sb() const;
|
||||
bool constrain_cb() const;
|
||||
|
@ -28,6 +29,7 @@ class PnrSdcOption {
|
|||
void set_sdc_dir(const std::string& sdc_dir);
|
||||
void set_generate_sdc_pnr(const bool& generate_sdc_pnr);
|
||||
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_sb(const bool& constrain_sb);
|
||||
void set_constrain_cb(const bool& constrain_cb);
|
||||
|
@ -37,6 +39,7 @@ class PnrSdcOption {
|
|||
private: /* Internal data */
|
||||
std::string sdc_dir_;
|
||||
bool constrain_global_port_;
|
||||
bool constrain_non_clock_global_port_;
|
||||
bool constrain_grid_;
|
||||
bool constrain_sb_;
|
||||
bool constrain_cb_;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "sdc_writer_naming.h"
|
||||
#include "sdc_writer_utils.h"
|
||||
#include "sdc_memory_utils.h"
|
||||
#include "pnr_sdc_global_port.h"
|
||||
#include "pnr_sdc_routing_writer.h"
|
||||
#include "pnr_sdc_grid_writer.h"
|
||||
#include "pnr_sdc_writer.h"
|
||||
|
@ -35,105 +36,6 @@
|
|||
/* begin 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
|
||||
* configurable memory cells.
|
||||
|
@ -354,7 +256,8 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
|
|||
print_pnr_sdc_global_ports(sdc_options.sdc_dir(),
|
||||
programming_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();
|
||||
|
|
Loading…
Reference in New Issue