Skip to content

Commit 4533dde

Browse files
[STA] Added Option to Remove Parameters from Post-Implementation Netlist
When performing post-implementation timing analysis using OpenSTA, the generated netlist cannot use parameters since each module needs to correspond with a cell in a liberty file. Added a command-line option which tells the netlist writer to not use parameters when generating the netlist. If a primitive cannot be generated without using parameters, it will error out.
1 parent d5dc5f7 commit 4533dde

12 files changed

+112
-51
lines changed

doc/src/vpr/command_line_usage.rst

+10
Original file line numberDiff line numberDiff line change
@@ -1730,6 +1730,16 @@ Analysis Options
17301730

17311731
**Default:** ``unconnected``
17321732

1733+
.. option:: --post_synth_netlist_module_parameters { on | off }
1734+
1735+
Controls whether the post-synthesis netlist modules should use Verilog parameters
1736+
or not. When using the post-synthesis netlist for external timing analysis,
1737+
some tools cannot accept the netlist if it contains parameters. By setting
1738+
this option to ``off``, VPR will try to represent the netlist using non-parameterized
1739+
modules.
1740+
1741+
**Default:** ``on``
1742+
17331743
.. option:: --timing_report_npaths <int>
17341744

17351745
Controls how many timing paths are reported.

vpr/src/base/SetupVPR.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,7 @@ static void SetupAnalysisOpts(const t_options& Options, t_analysis_opts& analysi
714714

715715
analysis_opts.post_synth_netlist_unconn_input_handling = Options.post_synth_netlist_unconn_input_handling;
716716
analysis_opts.post_synth_netlist_unconn_output_handling = Options.post_synth_netlist_unconn_output_handling;
717+
analysis_opts.post_synth_netlist_module_parameters = Options.post_synth_netlist_module_parameters.value();
717718

718719
analysis_opts.timing_update_type = Options.timing_update_type;
719720
analysis_opts.write_timing_summary = Options.write_timing_summary;

vpr/src/base/ShowSetup.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@ static void ShowAnalysisOpts(const t_analysis_opts& AnalysisOpts) {
717717
VPR_FATAL_ERROR(VPR_ERROR_UNKNOWN, "Unknown post_synth_netlist_unconn_handling\n");
718718
}
719719
}
720+
VTR_LOG("AnalysisOpts.post_synth_netlist_module_parameters: %s\n", AnalysisOpts.post_synth_netlist_module_parameters ? "on" : "off");
720721
VTR_LOG("\n");
721722
}
722723

vpr/src/base/netlist_writer.cpp

+83-41
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ class LutInst : public Instance {
275275
std::map<std::string, std::vector<std::string>> port_conns, ///<The port connections of this instance. Key: port name, Value: connected nets
276276
std::vector<Arc> timing_arc_values, ///<The timing arcs of this instance
277277
struct t_analysis_opts opts)
278-
: type_("LUT_K")
278+
: type_(opts.post_synth_netlist_module_parameters ? "LUT_K" : "LUT_" + std::to_string(lut_size))
279279
, lut_size_(lut_size)
280280
, lut_mask_(lut_mask)
281281
, inst_name_(inst_name)
@@ -292,20 +292,33 @@ class LutInst : public Instance {
292292
public: //Instance interface method implementations
293293
void print_verilog(std::ostream& os, size_t& unconn_count, int depth) override {
294294
//Instantiate the lut
295-
os << indent(depth) << type_ << " #(\n";
295+
os << indent(depth) << type_;
296296

297-
os << indent(depth + 1) << ".K(" << lut_size_ << "),\n";
297+
// If module parameters are on, pass the lut size and the lut mask as parameters.
298+
if (opts_.post_synth_netlist_module_parameters) {
299+
os << " #(\n";
298300

299-
std::stringstream param_ss;
300-
param_ss << lut_mask_;
301-
os << indent(depth + 1) << ".LUT_MASK(" << param_ss.str() << ")\n";
301+
os << indent(depth + 1) << ".K(" << lut_size_ << "),\n";
302302

303-
os << indent(depth) << ") " << escape_verilog_identifier(inst_name_) << " (\n";
303+
std::stringstream param_ss;
304+
param_ss << lut_mask_;
305+
os << indent(depth + 1) << ".LUT_MASK(" << param_ss.str() << ")\n";
306+
307+
os << indent(depth) << ")";
308+
}
309+
310+
os << " " << escape_verilog_identifier(inst_name_) << " (\n";
304311

305312
VTR_ASSERT(port_conns_.count("in"));
306313
VTR_ASSERT(port_conns_.count("out"));
307314
VTR_ASSERT(port_conns_.size() == 2);
308315

316+
// If module parameters are not on, the mask of the lut will be passed
317+
// as input to the module.
318+
if (!opts_.post_synth_netlist_module_parameters) {
319+
os << indent(depth + 1) << ".mask(" << lut_mask_ << "),\n";
320+
}
321+
309322
print_verilog_port(os, unconn_count, "in", port_conns_["in"], PortType::INPUT, depth + 1, opts_);
310323
os << ","
311324
<< "\n";
@@ -497,16 +510,18 @@ class LatchInst : public Instance {
497510
std::map<std::string, std::string> port_conns, ///<Instance's port-to-net connections
498511
Type type, ///<Type of this latch
499512
vtr::LogicValue init_value, ///<Initial value of the latch
500-
DelayTriple tcq = DelayTriple(), ///<Clock-to-Q delay
501-
DelayTriple tsu = DelayTriple(), ///<Setup time
502-
DelayTriple thld = DelayTriple()) ///<Hold time
513+
DelayTriple tcq, ///<Clock-to-Q delay
514+
DelayTriple tsu, ///<Setup time
515+
DelayTriple thld, ///<Hold time
516+
t_analysis_opts opts)
503517
: instance_name_(inst_name)
504518
, port_connections_(port_conns)
505519
, type_(type)
506520
, initial_value_(init_value)
507521
, tcq_delay_triple_(tcq)
508522
, tsu_delay_triple_(tsu)
509-
, thld_delay_triple_(thld) {}
523+
, thld_delay_triple_(thld)
524+
, opts_(opts) {}
510525

511526
void print_blif(std::ostream& os, size_t& /*unconn_count*/, int depth = 0) override {
512527
os << indent(depth) << ".latch"
@@ -537,21 +552,29 @@ class LatchInst : public Instance {
537552
//Currently assume a standard DFF
538553
VTR_ASSERT(type_ == Type::RISING_EDGE);
539554

540-
os << indent(depth) << "DFF"
541-
<< " #(\n";
542-
os << indent(depth + 1) << ".INITIAL_VALUE(";
543-
if (initial_value_ == vtr::LogicValue::TRUE)
544-
os << "1'b1";
545-
else if (initial_value_ == vtr::LogicValue::FALSE)
546-
os << "1'b0";
547-
else if (initial_value_ == vtr::LogicValue::DONT_CARE)
548-
os << "1'bx";
549-
else if (initial_value_ == vtr::LogicValue::UNKOWN)
550-
os << "1'bx";
551-
else
552-
VTR_ASSERT(false);
553-
os << ")\n";
554-
os << indent(depth) << ") " << escape_verilog_identifier(instance_name_) << " (\n";
555+
os << indent(depth) << "DFF";
556+
557+
// If module parameters are turned on, pass in the initial value of the
558+
// register as a parameter.
559+
// Note: This initial value is only used for simulation.
560+
if (opts_.post_synth_netlist_module_parameters) {
561+
os << " #(\n";
562+
os << indent(depth + 1) << ".INITIAL_VALUE(";
563+
if (initial_value_ == vtr::LogicValue::TRUE)
564+
os << "1'b1";
565+
else if (initial_value_ == vtr::LogicValue::FALSE)
566+
os << "1'b0";
567+
else if (initial_value_ == vtr::LogicValue::DONT_CARE)
568+
os << "1'bx";
569+
else if (initial_value_ == vtr::LogicValue::UNKOWN)
570+
os << "1'bx";
571+
else
572+
VTR_ASSERT(false);
573+
os << ")\n";
574+
os << indent(depth) << ")";
575+
}
576+
577+
os << " " << escape_verilog_identifier(instance_name_) << " (\n";
555578

556579
for (auto iter = port_connections_.begin(); iter != port_connections_.end(); ++iter) {
557580
os << indent(depth + 1) << "." << iter->first << "(" << escape_verilog_identifier(iter->second) << ")";
@@ -607,6 +630,7 @@ class LatchInst : public Instance {
607630
DelayTriple tcq_delay_triple_; ///<Clock delay + tcq
608631
DelayTriple tsu_delay_triple_; ///<Setup time
609632
DelayTriple thld_delay_triple_; ///<Hold time
633+
t_analysis_opts opts_;
610634
};
611635

612636
class BlackBoxInst : public Instance {
@@ -677,25 +701,40 @@ class BlackBoxInst : public Instance {
677701

678702
void print_verilog(std::ostream& os, size_t& unconn_count, int depth = 0) override {
679703
//Instance type
680-
os << indent(depth) << type_name_ << " #(\n";
681-
682-
//Verilog parameters
683-
for (auto iter = params_.begin(); iter != params_.end(); ++iter) {
684-
/* Prepend a prefix if needed */
685-
std::stringstream prefix;
686-
if (is_binary_param(iter->second)) {
687-
prefix << iter->second.length() << "'b";
688-
}
704+
os << indent(depth) << type_name_;
705+
706+
// Print the parameters if any are provided.
707+
if (params_.size() > 0) {
708+
if (opts_.post_synth_netlist_module_parameters) {
709+
os << " #(\n";
710+
711+
//Verilog parameters
712+
for (auto iter = params_.begin(); iter != params_.end(); ++iter) {
713+
/* Prepend a prefix if needed */
714+
std::stringstream prefix;
715+
if (is_binary_param(iter->second)) {
716+
prefix << iter->second.length() << "'b";
717+
}
689718

690-
os << indent(depth + 1) << "." << iter->first << "(" << prefix.str() << iter->second << ")";
691-
if (iter != --params_.end()) {
692-
os << ",";
719+
os << indent(depth + 1) << "." << iter->first << "(" << prefix.str() << iter->second << ")";
720+
if (iter != --params_.end()) {
721+
os << ",";
722+
}
723+
os << "\n";
724+
}
725+
os << indent(depth) << ")";
726+
} else {
727+
// TODO: RAMs are considered black box instructions. These can
728+
// probably be handled similar to LUTs.
729+
VPR_FATAL_ERROR(VPR_ERROR_IMPL_NETLIST_WRITER,
730+
"Cannot generate black box instruction of type %s "
731+
"without using parameters.",
732+
type_name_.c_str());
693733
}
694-
os << "\n";
695734
}
696735

697736
//Instance name
698-
os << indent(depth) << ") " << escape_verilog_identifier(inst_name_) << " (\n";
737+
os << " " << escape_verilog_identifier(inst_name_) << " (\n";
699738

700739
//Input Port connections
701740
for (auto iter = input_port_conns_.begin(); iter != input_port_conns_.end(); ++iter) {
@@ -1325,6 +1364,9 @@ class NetlistWriterVisitor : public NetlistVisitor {
13251364
double tsu = pb_graph_node->input_pins[0][0].tsu;
13261365
DelayTriple tsu_triple(tsu, tsu, tsu);
13271366

1367+
double thld = pb_graph_node->input_pins[0][0].thld;
1368+
DelayTriple thld_triple(thld, thld, thld);
1369+
13281370
//Output (Q)
13291371
int output_cluster_pin_idx = pb_graph_node->output_pins[0][0].pin_count_in_cluster; //Unique pin index in cluster
13301372
VTR_ASSERT(top_pb_route.count(output_cluster_pin_idx));
@@ -1346,7 +1388,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
13461388
LatchInst::Type type = LatchInst::Type::RISING_EDGE;
13471389
vtr::LogicValue init_value = vtr::LogicValue::FALSE;
13481390

1349-
return std::make_shared<LatchInst>(inst_name, port_conns, type, init_value, tcq_triple, tsu_triple);
1391+
return std::make_shared<LatchInst>(inst_name, port_conns, type, init_value, tcq_triple, tsu_triple, thld_triple, opts_);
13501392
}
13511393

13521394
/**

vpr/src/base/read_options.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -2997,6 +2997,16 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio
29972997
.default_value("unconnected")
29982998
.show_in(argparse::ShowIn::HELP_ONLY);
29992999

3000+
analysis_grp.add_argument<bool, ParseOnOff>(args.post_synth_netlist_module_parameters, "--post_synth_netlist_module_parameters")
3001+
.help(
3002+
"Controls whether the post-synthesis netlist modules should use Verilog parameters "
3003+
"or not. When using the post-synthesis netlist for external timing analysis, "
3004+
"some tools cannot accept the netlist if it contains parameters. By setting "
3005+
"this option to off, VPR will try to represent the netlist using non-parameterized "
3006+
"modules\n")
3007+
.default_value("on")
3008+
.show_in(argparse::ShowIn::HELP_ONLY);
3009+
30003010
analysis_grp.add_argument(args.write_timing_summary, "--write_timing_summary")
30013011
.help("Writes implemented design final timing summary to the specified JSON, XML or TXT file.")
30023012
.show_in(argparse::ShowIn::HELP_ONLY);

vpr/src/base/read_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ struct t_options {
265265
argparse::ArgValue<std::string> echo_dot_timing_graph_node;
266266
argparse::ArgValue<e_post_synth_netlist_unconn_handling> post_synth_netlist_unconn_input_handling;
267267
argparse::ArgValue<e_post_synth_netlist_unconn_handling> post_synth_netlist_unconn_output_handling;
268+
argparse::ArgValue<bool> post_synth_netlist_module_parameters;
268269
argparse::ArgValue<std::string> write_timing_summary;
269270
};
270271

vpr/src/base/vpr_types.h

+1
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,7 @@ struct t_analysis_opts {
12791279
bool gen_post_implementation_merged_netlist;
12801280
e_post_synth_netlist_unconn_handling post_synth_netlist_unconn_input_handling;
12811281
e_post_synth_netlist_unconn_handling post_synth_netlist_unconn_output_handling;
1282+
bool post_synth_netlist_module_parameters;
12821283

12831284
int timing_report_npaths;
12841285
e_timing_report_detail timing_report_detail;

vpr/test/test_post_verilog_i_gnd_o_unconnected.golden.v

+1-2
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,7 @@ module unconnected (
199199
wire \__vpr__unconn7 ;
200200

201201
//Cell instances
202-
dsp #(
203-
) \dsp_inst (
202+
dsp \dsp_inst (
204203
.a({
205204
1'b0,
206205
1'b0,

vpr/test/test_post_verilog_i_nets_o_unconnected.golden.v

+1-2
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,7 @@ module unconnected (
204204
wire \__vpr__unconn12 ;
205205

206206
//Cell instances
207-
dsp #(
208-
) \dsp_inst (
207+
dsp \dsp_inst (
209208
.a({
210209
__vpr__unconn0,
211210
__vpr__unconn1,

vpr/test/test_post_verilog_i_unconnected_o_nets.golden.v

+1-2
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,7 @@ module unconnected (
200200
wire \__vpr__unconn8 ;
201201

202202
//Cell instances
203-
dsp #(
204-
) \dsp_inst (
203+
dsp \dsp_inst (
205204
.a({
206205
1'bX,
207206
1'bX,

vpr/test/test_post_verilog_i_unconnected_o_unconnected.golden.v

+1-2
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,7 @@ module unconnected (
199199
wire \__vpr__unconn7 ;
200200

201201
//Cell instances
202-
dsp #(
203-
) \dsp_inst (
202+
dsp \dsp_inst (
204203
.a({
205204
1'bX,
206205
1'bX,

vpr/test/test_post_verilog_i_vcc_o_unconnected.golden.v

+1-2
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,7 @@ module unconnected (
199199
wire \__vpr__unconn7 ;
200200

201201
//Cell instances
202-
dsp #(
203-
) \dsp_inst (
202+
dsp \dsp_inst (
204203
.a({
205204
1'b1,
206205
1'b1,

0 commit comments

Comments
 (0)