From 686aa51d4f058c7932cb381b1e3301d2f16ad9d3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Jun 2022 00:02:06 +0000 Subject: [PATCH 01/14] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index 1b2d909cc..9b2d076f7 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.1.274 +1.1.282 From 9fd8c02e13d3e9e07fae1d1e5a4448091803eef5 Mon Sep 17 00:00:00 2001 From: coolbreeze413 Date: Wed, 29 Jun 2022 07:03:38 +0530 Subject: [PATCH 02/14] header inclusions required for MinGW windows build --- libopenfpga/libarchopenfpga/src/arch_direct.h | 1 + libs/libvtrutil/src/vtr_small_vector.h | 1 + vpr/src/place/place.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/libopenfpga/libarchopenfpga/src/arch_direct.h b/libopenfpga/libarchopenfpga/src/arch_direct.h index 067b257d1..cbdf4cc8e 100644 --- a/libopenfpga/libarchopenfpga/src/arch_direct.h +++ b/libopenfpga/libarchopenfpga/src/arch_direct.h @@ -2,6 +2,7 @@ #define ARCH_DIRECT_H #include +#include #include "vtr_vector.h" #include "vtr_geometry.h" diff --git a/libs/libvtrutil/src/vtr_small_vector.h b/libs/libvtrutil/src/vtr_small_vector.h index 86f367f24..ce9540bc5 100644 --- a/libs/libvtrutil/src/vtr_small_vector.h +++ b/libs/libvtrutil/src/vtr_small_vector.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "vtr_assert.h" namespace vtr { diff --git a/vpr/src/place/place.cpp b/vpr/src/place/place.cpp index 0d82de03f..743b31ac3 100644 --- a/vpr/src/place/place.cpp +++ b/vpr/src/place/place.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "vtr_assert.h" #include "vtr_log.h" From 4673005fa64798941ede833015b4fa26ebbb24a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Jun 2022 06:27:47 +0000 Subject: [PATCH 03/14] Bump yosys-plugins from `c9af547` to `75df29e` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `c9af547` to `75df29e`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/c9af547bf7241d260e1c36af916926533e6ebfd5...75df29e1c68353d9c9b5b3db7f4748e057d3d6a1) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index c9af547bf..75df29e1c 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit c9af547bf7241d260e1c36af916926533e6ebfd5 +Subproject commit 75df29e1c68353d9c9b5b3db7f4748e057d3d6a1 From 26098625800030dcb9062ea7347ecf8335c6c8a6 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Tue, 28 Jun 2022 17:04:58 +0200 Subject: [PATCH 04/14] Interpretation of EBLIF parameters and correct writing them to output Verilog netlist Signed-off-by: Maciej Kurc --- vpr/src/base/netlist_writer.cpp | 10 ++++- vpr/src/base/read_blif.cpp | 71 +++++++++++++++++++++++++++++++++ vpr/src/base/read_blif.h | 4 ++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/vpr/src/base/netlist_writer.cpp b/vpr/src/base/netlist_writer.cpp index 41fcf09dd..4c663b21c 100644 --- a/vpr/src/base/netlist_writer.cpp +++ b/vpr/src/base/netlist_writer.cpp @@ -20,6 +20,8 @@ #include "vpr_error.h" #include "vpr_types.h" +#include "read_blif.h" + #include "netlist_walker.h" #include "netlist_writer.h" @@ -620,7 +622,13 @@ class BlackBoxInst : public Instance { //Verilog parameters for (auto iter = params_.begin(); iter != params_.end(); ++iter) { - os << indent(depth + 1) << "." << iter->first << "(" << iter->second << ")"; + /* Prepend a prefix if needed */ + std::stringstream prefix; + if (is_binary_param(iter->second)) { + prefix << iter->second.length() << "'b"; + } + + os << indent(depth + 1) << "." << iter->first << "(" << prefix.str() << iter->second << ")"; if (iter != --params_.end()) { os << ","; } diff --git a/vpr/src/base/read_blif.cpp b/vpr/src/base/read_blif.cpp index 966794574..965ccf40f 100644 --- a/vpr/src/base/read_blif.cpp +++ b/vpr/src/base/read_blif.cpp @@ -21,6 +21,8 @@ #include #include #include //std::isdigit +#include +#include #include "blifparse.hpp" #include "atom_netlist.h" @@ -382,6 +384,14 @@ struct BlifAllocCallback : public blifparse::Callback { parse_error(lineno_, ".param", "Supported only in extended BLIF format"); } + // Validate the parameter value + bool is_valid = is_string_param(value) || is_binary_param(value) || is_real_param(value); + + if (!is_valid) { + std::string msg = "Incorrect parameter '" + name + "' value specification. Value '" + value + "' is not recognized as string, binary word or real number. Possible causes:\n\t* lack or inconsistency in quotes (string)\n\t* no dot '.' to separate integer and fractional part (real number)\n\t* use of characters other than '1' and '0' (binary word)"; + parse_error(lineno_, ".param", msg); + } + curr_model().set_block_param(curr_block(), name, value); } @@ -655,6 +665,67 @@ vtr::LogicValue to_vtr_logic_value(blifparse::LogicValue val) { return new_val; } +bool is_string_param(const std::string& param) { + /* Empty param is considered a string */ + if (param.empty()) { + return true; + } + + /* There have to be at least 2 characters (the quotes) */ + if (param.length() < 2) { + return false; + } + + /* The first and the last characters must be quotes */ + size_t len = param.length(); + if (param[0] != '"' || param[len - 1] != '"') { + return false; + } + + /* There mustn't be any other quotes except for escaped ones */ + for (size_t i = 1; i < (len - 1); ++i) { + if (param[i] == '"' && param[i - 1] != '\\') { + return false; + } + } + + /* This is a string param */ + return true; +} + +bool is_binary_param(const std::string& param) { + /* Must be non-empty */ + if (param.empty()) { + return false; + } + + /* The string must contain only '0' and '1' */ + for (size_t i = 0; i < param.length(); ++i) { + if (param[i] != '0' && param[i] != '1') { + return false; + } + } + + /* This is a binary word param */ + return true; +} + +bool is_real_param(const std::string& param) { + /* Must be non-empty */ + if (param.empty()) { + return false; + } + + /* The string must match the regular expression */ + static const std::regex real_number_expr("[+-]?([0-9]*\\.[0-9]+)|([0-9]+\\.[0-9]*)"); + if (!std::regex_match(param, real_number_expr)) { + return false; + } + + /* This is a real number param */ + return true; +} + AtomNetlist read_blif(e_circuit_format circuit_format, const char* blif_file, const t_model* user_models, diff --git a/vpr/src/base/read_blif.h b/vpr/src/base/read_blif.h index 819bb035e..a11ba4ecb 100644 --- a/vpr/src/base/read_blif.h +++ b/vpr/src/base/read_blif.h @@ -4,6 +4,10 @@ #include "atom_netlist_fwd.h" #include "read_circuit.h" +bool is_string_param(const std::string& param); +bool is_binary_param(const std::string& param); +bool is_real_param(const std::string& param); + AtomNetlist read_blif(e_circuit_format circuit_format, const char* blif_file, const t_model* user_models, From 782cdfd8e1e6c4d4d0a2f6e7d0d1b950d2c9d0e4 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Tue, 28 Jun 2022 17:24:15 +0200 Subject: [PATCH 05/14] Added VPR commandline options that control unconnected port handling in the output Verilog netlist Signed-off-by: Maciej Kurc --- vpr/src/base/SetupVPR.cpp | 3 ++ vpr/src/base/ShowSetup.cpp | 25 +++++++++ vpr/src/base/netlist_writer.cpp | 73 ++++++++++++++++++-------- vpr/src/base/netlist_writer.h | 2 +- vpr/src/base/read_options.cpp | 91 +++++++++++++++++++++++++++++++++ vpr/src/base/read_options.h | 2 + vpr/src/base/vpr_api.cpp | 3 +- vpr/src/base/vpr_types.h | 9 ++++ 8 files changed, 184 insertions(+), 24 deletions(-) diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index 8e806d515..ca7ec3bf7 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -528,6 +528,9 @@ static void SetupAnalysisOpts(const t_options& Options, t_analysis_opts& analysi analysis_opts.timing_report_npaths = Options.timing_report_npaths; analysis_opts.timing_report_detail = Options.timing_report_detail; analysis_opts.timing_report_skew = Options.timing_report_skew; + + analysis_opts.post_synth_netlist_unconn_input_handling = Options.post_synth_netlist_unconn_input_handling; + analysis_opts.post_synth_netlist_unconn_output_handling = Options.post_synth_netlist_unconn_output_handling; } static void SetupPowerOpts(const t_options& Options, t_power_opts* power_opts, t_arch* Arch) { diff --git a/vpr/src/base/ShowSetup.cpp b/vpr/src/base/ShowSetup.cpp index 05501cc9c..cdbf9afdf 100644 --- a/vpr/src/base/ShowSetup.cpp +++ b/vpr/src/base/ShowSetup.cpp @@ -384,6 +384,31 @@ static void ShowNetlistOpts(const t_netlist_opts& NetlistOpts) { static void ShowAnalysisOpts(const t_analysis_opts& AnalysisOpts) { VTR_LOG("AnalysisOpts.gen_post_synthesis_netlist: %s\n", (AnalysisOpts.gen_post_synthesis_netlist) ? "true" : "false"); + + const auto opts = { + std::make_tuple(&AnalysisOpts.post_synth_netlist_unconn_input_handling, "post_synth_netlist_unconn_input_handling"), + std::make_tuple(&AnalysisOpts.post_synth_netlist_unconn_output_handling, "post_synth_netlist_unconn_output_handling"), + }; + for (const auto& opt : opts) { + auto value = *std::get<0>(opt); + VTR_LOG("AnalysisOpts.%s: ", std::get<1>(opt)); + switch (value) { + case e_post_synth_netlist_unconn_handling::UNCONNECTED: + VTR_LOG("UNCONNECTED\n"); + break; + case e_post_synth_netlist_unconn_handling::NETS: + VTR_LOG("NETS\n"); + break; + case e_post_synth_netlist_unconn_handling::GND: + VTR_LOG("GND\n"); + break; + case e_post_synth_netlist_unconn_handling::VCC: + VTR_LOG("VCC\n"); + break; + default: + VPR_FATAL_ERROR(VPR_ERROR_UNKNOWN, "Unknown post_synth_netlist_unconn_handling\n"); + } + } VTR_LOG("\n"); } diff --git a/vpr/src/base/netlist_writer.cpp b/vpr/src/base/netlist_writer.cpp index 41fcf09dd..19d7d0388 100644 --- a/vpr/src/base/netlist_writer.cpp +++ b/vpr/src/base/netlist_writer.cpp @@ -111,7 +111,7 @@ std::string indent(size_t depth); double get_delay_ps(double delay_sec); void print_blif_port(std::ostream& os, size_t& unconn_count, const std::string& port_name, const std::vector& nets, int depth); -void print_verilog_port(std::ostream& os, size_t& unconn_count, const std::string& port_name, const std::vector& nets, PortType type, int depth); +void print_verilog_port(std::ostream& os, size_t& unconn_count, const std::string& port_name, const std::vector& nets, PortType type, int depth, struct t_analysis_opts& opts); std::string create_unconn_net(size_t& unconn_count); std::string escape_verilog_identifier(const std::string id); @@ -201,13 +201,15 @@ class LutInst : public Instance { LogicVec lut_mask, ///> port_conns, /// timing_arc_values) /// timing_arc_values, ///> port_conns_; std::vector timing_arcs_; + struct t_analysis_opts opts_; }; class LatchInst : public Instance { @@ -561,7 +564,8 @@ class BlackBoxInst : public Instance { std::vector timing_arcs, /// ports_tsu, /// ports_thld, /// ports_tcq) /// ports_tcq, ///first; auto& nets = iter->second; - print_verilog_port(os, unconn_count, port_name, nets, PortType::INPUT, depth + 1); + print_verilog_port(os, unconn_count, port_name, nets, PortType::INPUT, depth + 1, opts_); if (!(iter == --input_port_conns_.end() && output_port_conns_.empty())) { os << ","; } @@ -645,7 +650,7 @@ class BlackBoxInst : public Instance { for (auto iter = output_port_conns_.begin(); iter != output_port_conns_.end(); ++iter) { auto& port_name = iter->first; auto& nets = iter->second; - print_verilog_port(os, unconn_count, port_name, nets, PortType::OUTPUT, depth + 1); + print_verilog_port(os, unconn_count, port_name, nets, PortType::OUTPUT, depth + 1, opts_); if (!(iter == --output_port_conns_.end())) { os << ","; } @@ -756,6 +761,7 @@ class BlackBoxInst : public Instance { std::map ports_tsu_; std::map ports_thld_; std::map ports_tcq_; + struct t_analysis_opts opts_; }; /** @@ -794,11 +800,13 @@ class NetlistWriterVisitor : public NetlistVisitor { NetlistWriterVisitor(std::ostream& verilog_os, /// delay_calc) + std::shared_ptr delay_calc, + struct t_analysis_opts opts) : verilog_os_(verilog_os) , blif_os_(blif_os) , sdf_os_(sdf_os) - , delay_calc_(delay_calc) { + , delay_calc_(delay_calc) + , opts_(opts) { auto& atom_ctx = g_vpr_ctx.atom(); //Initialize the pin to tnode look-up @@ -1213,7 +1221,7 @@ class NetlistWriterVisitor : public NetlistVisitor { port_conns["out"].push_back(net); } - auto inst = std::make_shared(lut_size, lut_mask, inst_name, port_conns, timing_arcs); + auto inst = std::make_shared(lut_size, lut_mask, inst_name, port_conns, timing_arcs, opts_); return inst; } @@ -1413,7 +1421,7 @@ class NetlistWriterVisitor : public NetlistVisitor { } } - return std::make_shared(type, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq); + return std::make_shared(type, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq, opts_); } ///@brief Returns an Instance object representing a Multiplier @@ -1509,7 +1517,7 @@ class NetlistWriterVisitor : public NetlistVisitor { VTR_ASSERT(pb_graph_node->num_clock_ports == 0); //No clocks - return std::make_shared(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq); + return std::make_shared(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq, opts_); } ///@brief Returns an Instance object representing an Adder @@ -1609,7 +1617,7 @@ class NetlistWriterVisitor : public NetlistVisitor { } } - return std::make_shared(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq); + return std::make_shared(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq, opts_); } std::shared_ptr make_blackbox_instance(const t_pb* atom) { @@ -1747,7 +1755,7 @@ class NetlistWriterVisitor : public NetlistVisitor { attrs[attr.first] = attr.second; } - return std::make_shared(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq); + return std::make_shared(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq, opts_); } ///@brief Returns the top level pb_route associated with the given pb @@ -2067,6 +2075,7 @@ class NetlistWriterVisitor : public NetlistVisitor { std::map, tatum::NodeId> pin_id_to_tnode_lookup_; std::shared_ptr delay_calc_; + struct t_analysis_opts opts_; }; // @@ -2074,7 +2083,7 @@ class NetlistWriterVisitor : public NetlistVisitor { // ///@brief Main routing for this file. See netlist_writer.h for details. -void netlist_writer(const std::string basename, std::shared_ptr delay_calc) { +void netlist_writer(const std::string basename, std::shared_ptr delay_calc, struct t_analysis_opts opts) { std::string verilog_filename = basename + "_post_synthesis.v"; std::string blif_filename = basename + "_post_synthesis.blif"; std::string sdf_filename = basename + "_post_synthesis.sdf"; @@ -2087,7 +2096,7 @@ void netlist_writer(const std::string basename, std::shared_ptr& nets, PortType type, int depth) { +void print_verilog_port(std::ostream& os, size_t& unconn_count, const std::string& port_name, const std::vector& nets, PortType type, int depth, struct t_analysis_opts& opts) { //Port name os << indent(depth) << "." << port_name << "("; @@ -2169,10 +2178,30 @@ void print_verilog_port(std::ostream& os, size_t& unconn_count, const std::strin if (nets[0].empty()) { //Disconnected if (type == PortType::INPUT || type == PortType::CLOCK) { - os << "1'b0"; + switch (opts.post_synth_netlist_unconn_input_handling) { + case e_post_synth_netlist_unconn_handling::GND: + os << "1'b0"; + break; + case e_post_synth_netlist_unconn_handling::VCC: + os << "1'b1"; + break; + case e_post_synth_netlist_unconn_handling::NETS: + os << create_unconn_net(unconn_count); + break; + case e_post_synth_netlist_unconn_handling::UNCONNECTED: + default: + os << "1'bX"; + } } else { VTR_ASSERT(type == PortType::OUTPUT); - os << create_unconn_net(unconn_count); + switch (opts.post_synth_netlist_unconn_output_handling) { + case e_post_synth_netlist_unconn_handling::NETS: + os << create_unconn_net(unconn_count); + break; + case e_post_synth_netlist_unconn_handling::UNCONNECTED: + default: + os << "1'bX"; + } } } else { //Connected @@ -2191,7 +2220,7 @@ void print_verilog_port(std::ostream& os, size_t& unconn_count, const std::strin os << "1'b0"; } else { VTR_ASSERT(type == PortType::OUTPUT); - os << create_unconn_net(unconn_count); + os << ""; } } else { //Connected diff --git a/vpr/src/base/netlist_writer.h b/vpr/src/base/netlist_writer.h index 8f3b4e8a6..9c4306de7 100644 --- a/vpr/src/base/netlist_writer.h +++ b/vpr/src/base/netlist_writer.h @@ -15,6 +15,6 @@ * All written filenames end in {basename}_post_synthesis.{fmt} where {basename} is the * basename argument and {fmt} is the file format (e.g. v, blif, sdf) */ -void netlist_writer(const std::string basename, std::shared_ptr delay_calc); +void netlist_writer(const std::string basename, std::shared_ptr delay_calc, struct t_analysis_opts opts); #endif diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index 5f654445e..0e0af27f4 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -755,6 +755,75 @@ struct ParseReducer { return {"min", "max", "median", "arithmean", "geomean"}; } }; +struct ParsePostSynthNetlistUnconnInputHandling { + ConvertedValue from_str(std::string str) { + ConvertedValue conv_value; + if (str == "unconnected") + conv_value.set_value(e_post_synth_netlist_unconn_handling::UNCONNECTED); + else if (str == "nets") + conv_value.set_value(e_post_synth_netlist_unconn_handling::NETS); + else if (str == "gnd") + conv_value.set_value(e_post_synth_netlist_unconn_handling::GND); + else if (str == "vcc") + conv_value.set_value(e_post_synth_netlist_unconn_handling::VCC); + else { + std::stringstream msg; + msg << "Invalid conversion from '" << str << "' to e_post_synth_netlist_unconn_handling (expected one of: " << argparse::join(default_choices(), ", ") << ")"; + conv_value.set_error(msg.str()); + } + return conv_value; + } + + ConvertedValue to_str(e_post_synth_netlist_unconn_handling val) { + ConvertedValue conv_value; + if (val == e_post_synth_netlist_unconn_handling::NETS) + conv_value.set_value("nets"); + else if (val == e_post_synth_netlist_unconn_handling::GND) + conv_value.set_value("gnd"); + else if (val == e_post_synth_netlist_unconn_handling::VCC) + conv_value.set_value("vcc"); + else { + VTR_ASSERT(val == e_post_synth_netlist_unconn_handling::UNCONNECTED); + conv_value.set_value("unconnected"); + } + return conv_value; + } + + std::vector default_choices() { + return {"unconnected", "nets", "gnd", "vcc"}; + } +}; + +struct ParsePostSynthNetlistUnconnOutputHandling { + ConvertedValue from_str(std::string str) { + ConvertedValue conv_value; + if (str == "unconnected") + conv_value.set_value(e_post_synth_netlist_unconn_handling::UNCONNECTED); + else if (str == "nets") + conv_value.set_value(e_post_synth_netlist_unconn_handling::NETS); + else { + std::stringstream msg; + msg << "Invalid conversion from '" << str << "' to e_post_synth_netlist_unconn_handling (expected one of: " << argparse::join(default_choices(), ", ") << ")"; + conv_value.set_error(msg.str()); + } + return conv_value; + } + + ConvertedValue to_str(e_post_synth_netlist_unconn_handling val) { + ConvertedValue conv_value; + if (val == e_post_synth_netlist_unconn_handling::NETS) + conv_value.set_value("nets"); + else { + VTR_ASSERT(val == e_post_synth_netlist_unconn_handling::UNCONNECTED); + conv_value.set_value("unconnected"); + } + return conv_value; + } + + std::vector default_choices() { + return {"unconnected", "nets"}; + } +}; argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& args) { std::string description = @@ -1675,6 +1744,28 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg .default_value("off") .show_in(argparse::ShowIn::HELP_ONLY); + analysis_grp.add_argument(args.post_synth_netlist_unconn_input_handling, "--post_synth_netlist_unconn_inputs") + .help( + "Controls how unconnected input cell ports are handled in the post-synthesis netlist\n" + " * unconnected: leave unconnected\n" + " * nets: connect each unconnected input pin to its own separate\n" + " undriven net named: __vpr__unconn, where is index\n" + " assigned to this occurrence of unconnected port in design\n" + " * gnd: tie all to ground (1'b0)\n" + " * vcc: tie all to VCC (1'b1)\n") + .default_value("unconnected") + .show_in(argparse::ShowIn::HELP_ONLY); + + analysis_grp.add_argument(args.post_synth_netlist_unconn_output_handling, "--post_synth_netlist_unconn_outputs") + .help( + "Controls how unconnected output cell ports are handled in the post-synthesis netlist\n" + " * unconnected: leave unconnected\n" + " * nets: connect each unconnected input pin to its own separate\n" + " undriven net named: __vpr__unconn, where is index\n" + " assigned to this occurrence of unconnected port in design\n") + .default_value("unconnected") + .show_in(argparse::ShowIn::HELP_ONLY); + auto& power_grp = parser.add_argument_group("power analysis options"); power_grp.add_argument(args.do_power, "--power") diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h index 97d320abb..a4ee70993 100644 --- a/vpr/src/base/read_options.h +++ b/vpr/src/base/read_options.h @@ -159,6 +159,8 @@ struct t_options { argparse::ArgValue timing_report_npaths; argparse::ArgValue timing_report_detail; argparse::ArgValue timing_report_skew; + argparse::ArgValue post_synth_netlist_unconn_input_handling; + argparse::ArgValue post_synth_netlist_unconn_output_handling; }; argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& args); diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 846c0779a..266c8ba9b 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -1195,7 +1195,8 @@ void vpr_analysis(t_vpr_setup& vpr_setup, const t_arch& Arch, const RouteStatus& //Write the post-syntesis netlist if (vpr_setup.AnalysisOpts.gen_post_synthesis_netlist) { - netlist_writer(atom_ctx.nlist.netlist_name().c_str(), analysis_delay_calc); + netlist_writer(atom_ctx.nlist.netlist_name().c_str(), analysis_delay_calc, + vpr_setup.AnalysisOpts); } //Do power analysis diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index f6696dd9f..13a7aa2f3 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -900,6 +900,13 @@ enum class e_timing_report_detail { DETAILED_ROUTING, //Show inter-block routing resources used }; +enum class e_post_synth_netlist_unconn_handling { + UNCONNECTED, // Leave unrouted ports unconnected + NETS, // Leave unrouted ports unconnected but add new named nets to each of them + GND, // Tie unrouted ports to ground (only for input ports) + VCC // Tie unrouted ports to VCC (only for input ports) +}; + enum class e_incr_reroute_delay_ripup { ON, OFF, @@ -959,6 +966,8 @@ struct t_analysis_opts { e_stage_action doAnalysis; bool gen_post_synthesis_netlist; + e_post_synth_netlist_unconn_handling post_synth_netlist_unconn_input_handling; + e_post_synth_netlist_unconn_handling post_synth_netlist_unconn_output_handling; int timing_report_npaths; e_timing_report_detail timing_report_detail; From 721ac996968eb447498ffca960bed1973da9a734 Mon Sep 17 00:00:00 2001 From: Maciej Kurc Date: Thu, 30 Jun 2022 12:57:05 +0200 Subject: [PATCH 06/14] Correct handling of unconnected ports in output Verilog netlist... ...so that outputs are not connected to constants. Signed-off-by: Maciej Kurc --- vpr/src/base/netlist_writer.cpp | 125 ++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 45 deletions(-) diff --git a/vpr/src/base/netlist_writer.cpp b/vpr/src/base/netlist_writer.cpp index 19d7d0388..749039c96 100644 --- a/vpr/src/base/netlist_writer.cpp +++ b/vpr/src/base/netlist_writer.cpp @@ -125,6 +125,9 @@ std::string join_identifier(std::string lhs, std::string rhs); // // +// Unconnected net prefix +const std::string unconn_prefix = "__vpr__unconn"; + //A combinational timing arc class Arc { public: @@ -945,6 +948,16 @@ class NetlistWriterVisitor : public NetlistVisitor { inst->print_verilog(verilog_os_, unconn_count, depth + 1); } + //Unconnected wires + if (unconn_count) { + verilog_os_ << "\n"; + verilog_os_ << indent(depth + 1) << "//Unconnected wires\n"; + for (size_t i = 0; i < unconn_count; ++i) { + auto name = unconn_prefix + std::to_string(i); + verilog_os_ << indent(depth + 1) << "wire " << escape_verilog_identifier(name) << ";\n"; + } + } + verilog_os_ << "\n"; verilog_os_ << indent(depth) << "endmodule\n"; } @@ -2126,7 +2139,7 @@ double get_delay_ps(double delay_sec) { std::string create_unconn_net(size_t& unconn_count) { //We increment unconn_count by reference so each //call generates a unique name - return "__vpr__unconn" + std::to_string(unconn_count++); + return unconn_prefix + std::to_string(unconn_count++); } /** @@ -2169,6 +2182,30 @@ void print_blif_port(std::ostream& os, size_t& unconn_count, const std::string& * Handles special cases like multi-bit and disconnected ports */ void print_verilog_port(std::ostream& os, size_t& unconn_count, const std::string& port_name, const std::vector& nets, PortType type, int depth, struct t_analysis_opts& opts) { + auto unconn_inp_name = [&]() { + switch (opts.post_synth_netlist_unconn_input_handling) { + case e_post_synth_netlist_unconn_handling::GND: + return std::string("1'b0"); + case e_post_synth_netlist_unconn_handling::VCC: + return std::string("1'b1"); + case e_post_synth_netlist_unconn_handling::NETS: + return create_unconn_net(unconn_count); + case e_post_synth_netlist_unconn_handling::UNCONNECTED: + default: + return std::string("1'bX"); + } + }; + + auto unconn_out_name = [&]() { + switch (opts.post_synth_netlist_unconn_output_handling) { + case e_post_synth_netlist_unconn_handling::NETS: + return create_unconn_net(unconn_count); + case e_post_synth_netlist_unconn_handling::UNCONNECTED: + default: + return std::string(); + } + }; + //Port name os << indent(depth) << "." << port_name << "("; @@ -2178,60 +2215,58 @@ void print_verilog_port(std::ostream& os, size_t& unconn_count, const std::strin if (nets[0].empty()) { //Disconnected if (type == PortType::INPUT || type == PortType::CLOCK) { - switch (opts.post_synth_netlist_unconn_input_handling) { - case e_post_synth_netlist_unconn_handling::GND: - os << "1'b0"; - break; - case e_post_synth_netlist_unconn_handling::VCC: - os << "1'b1"; - break; - case e_post_synth_netlist_unconn_handling::NETS: - os << create_unconn_net(unconn_count); - break; - case e_post_synth_netlist_unconn_handling::UNCONNECTED: - default: - os << "1'bX"; - } + os << unconn_inp_name(); } else { VTR_ASSERT(type == PortType::OUTPUT); - switch (opts.post_synth_netlist_unconn_output_handling) { - case e_post_synth_netlist_unconn_handling::NETS: - os << create_unconn_net(unconn_count); - break; - case e_post_synth_netlist_unconn_handling::UNCONNECTED: - default: - os << "1'bX"; - } + os << unconn_out_name(); } } else { //Connected os << escape_verilog_identifier(nets[0]); } } else { - //A multi-bit port, we explicitly concat the single-bit nets to build the port, - //taking care to print MSB on left and LSB on right - os << "{" - << "\n"; - for (int ipin = (int)nets.size() - 1; ipin >= 0; --ipin) { //Reverse order to match endianess - os << indent(depth + 1); - if (nets[ipin].empty()) { - //Disconnected - if (type == PortType::INPUT || type == PortType::CLOCK) { - os << "1'b0"; - } else { - VTR_ASSERT(type == PortType::OUTPUT); - os << ""; - } - } else { - //Connected - os << escape_verilog_identifier(nets[ipin]); - } - if (ipin != 0) { - os << ","; - os << "\n"; + // Check if all pins are unconnected + bool all_unconnected = true; + for (size_t i = 0; i < nets.size(); ++i) { + if (!nets[i].empty()) { + all_unconnected = false; + break; } } - os << "}"; + + + //A multi-bit port, we explicitly concat the single-bit nets to build the port, + //taking care to print MSB on left and LSB on right + if (all_unconnected && type == PortType::OUTPUT && opts.post_synth_netlist_unconn_output_handling == e_post_synth_netlist_unconn_handling::UNCONNECTED) { + // Empty connection + } else { + // Individual bits + os << "{" + << "\n"; + for (int ipin = (int)nets.size() - 1; ipin >= 0; --ipin) { //Reverse order to match endianess + os << indent(depth + 1); + if (nets[ipin].empty()) { + //Disconnected + if (type == PortType::INPUT || type == PortType::CLOCK) { + os << unconn_inp_name(); + } else { + VTR_ASSERT(type == PortType::OUTPUT); + // When concatenating output connection there cannot + // be an empty placeholder so we have to create a + // dummy net. + os << create_unconn_net(unconn_count); + } + } else { + //Connected + os << escape_verilog_identifier(nets[ipin]); + } + if (ipin != 0) { + os << ","; + } + os << "\n"; + } + os << indent(depth) + " }"; + } } os << ")"; } From 46a3b9303f549d0b26e3ca3cdc58c0cb44dfb45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Czarnecki?= Date: Thu, 30 Jun 2022 14:17:26 +0200 Subject: [PATCH 07/14] vpr: add merged verilog netlist writer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Czarnecki --- vpr/src/base/SetupVPR.cpp | 1 + vpr/src/base/netlist_writer.cpp | 359 +++++++++++++++++++++++++------- vpr/src/base/netlist_writer.h | 10 + vpr/src/base/read_options.cpp | 7 + vpr/src/base/read_options.h | 1 + vpr/src/base/vpr_api.cpp | 5 + vpr/src/base/vpr_types.h | 1 + 7 files changed, 314 insertions(+), 70 deletions(-) diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index ca7ec3bf7..45b289cf8 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -524,6 +524,7 @@ static void SetupAnalysisOpts(const t_options& Options, t_analysis_opts& analysi } analysis_opts.gen_post_synthesis_netlist = Options.Generate_Post_Synthesis_Netlist; + analysis_opts.gen_post_implementation_merged_netlist = Options.Generate_Post_Implementation_Merged_Netlist; analysis_opts.timing_report_npaths = Options.timing_report_npaths; analysis_opts.timing_report_detail = Options.timing_report_detail; diff --git a/vpr/src/base/netlist_writer.cpp b/vpr/src/base/netlist_writer.cpp index 749039c96..285678175 100644 --- a/vpr/src/base/netlist_writer.cpp +++ b/vpr/src/base/netlist_writer.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "vtr_assert.h" #include "vtr_util.h" @@ -687,12 +688,12 @@ class BlackBoxInst : public Instance { os << indent(depth + 3) << "(IOPATH "; os << escape_sdf_identifier(arc.source_name()); if (find_port_size(arc.source_name()) > 1) { - os << "[" << arc.source_ipin() << "]"; + os << "\\[" << arc.source_ipin() << "\\]"; } os << " "; os << escape_sdf_identifier(arc.sink_name()); if (find_port_size(arc.sink_name()) > 1) { - os << "[" << arc.sink_ipin() << "]"; + os << "\\[" << arc.sink_ipin() << "\\]"; } os << " "; os << delay_triple.str(); @@ -783,6 +784,11 @@ class Assignment { void print_verilog(std::ostream& os, std::string indent) { os << indent << "assign " << escape_verilog_identifier(lval_) << " = " << escape_verilog_identifier(rval_) << ";\n"; } + + void print_merged_verilog(std::ostream& os, std::string indent) { + os << indent << "assign " << lval_ << " = " << rval_ << ";\n"; + } + void print_blif(std::ostream& os, std::string indent) { os << indent << ".names " << rval_ << " " << lval_ << "\n"; os << indent << "1 1\n"; @@ -878,12 +884,8 @@ class NetlistWriterVisitor : public NetlistVisitor { print_sdf(); } - private: //Internal Helper functions - ///@brief Writes out the verilog netlist - void print_verilog(int depth = 0) { - verilog_os_ << indent(depth) << "//Verilog generated by VPR " << vtr::VERSION << " from post-place-and-route implementation\n"; - verilog_os_ << indent(depth) << "module " << top_module_name_ << " (\n"; - + protected: + virtual void print_primary_io(int depth) { //Primary Inputs for (auto iter = inputs_.begin(); iter != inputs_.end(); ++iter) { verilog_os_ << indent(depth + 1) << "input " << escape_verilog_identifier(*iter); @@ -892,7 +894,6 @@ class NetlistWriterVisitor : public NetlistVisitor { } verilog_os_ << "\n"; } - //Primary Outputs for (auto iter = outputs_.begin(); iter != outputs_.end(); ++iter) { verilog_os_ << indent(depth + 1) << "output " << escape_verilog_identifier(*iter); @@ -901,6 +902,22 @@ class NetlistWriterVisitor : public NetlistVisitor { } verilog_os_ << "\n"; } + } + + virtual void print_assignments(int depth) { + verilog_os_ << "\n"; + verilog_os_ << indent(depth + 1) << "//IO assignments\n"; + for (auto& assign : assignments_) { + assign.print_verilog(verilog_os_, indent(depth + 1)); + } + } + + ///@brief Writes out the verilog netlist + void print_verilog(int depth = 0) { + verilog_os_ << indent(depth) << "//Verilog generated by VPR " << vtr::VERSION << " from post-place-and-route implementation\n"; + verilog_os_ << indent(depth) << "module " << top_module_name_ << " (\n"; + + print_primary_io(depth); verilog_os_ << indent(depth) << ");\n"; //Wire declarations @@ -916,11 +933,7 @@ class NetlistWriterVisitor : public NetlistVisitor { } //connections between primary I/Os and their internal wires - verilog_os_ << "\n"; - verilog_os_ << indent(depth + 1) << "//IO assignments\n"; - for (auto& assign : assignments_) { - assign.print_verilog(verilog_os_, indent(depth + 1)); - } + print_assignments(depth); //Interconnect between cell instances verilog_os_ << "\n"; @@ -962,6 +975,7 @@ class NetlistWriterVisitor : public NetlistVisitor { verilog_os_ << indent(depth) << "endmodule\n"; } + private: //Internal Helper functions ///@brief Writes out the blif netlist void print_blif(int depth = 0) { blif_os_ << indent(depth) << "#BLIF generated by VPR " << vtr::VERSION << " from post-place-and-route implementation\n"; @@ -1066,47 +1080,6 @@ class NetlistWriterVisitor : public NetlistVisitor { sdf_os_ << indent(depth) << ")\n"; } - /** - * @brief Returns the name of a wire connecting a primitive and global net. - * - * The wire is recorded and instantiated by the top level output routines. - */ - std::string make_inst_wire(AtomNetId atom_net_id, /// make_lut_instance(const t_pb* atom) { //Determine what size LUT @@ -1777,18 +1792,6 @@ class NetlistWriterVisitor : public NetlistVisitor { return top_pb->pb_route; } - ///@brief Returns the top complex block which contains the given pb - const t_pb* find_top_cb(const t_pb* curr) { - //Walk up through the pb graph until curr - //has no parent, at which point it will be the top pb - const t_pb* parent = curr->parent_pb; - while (parent != nullptr) { - curr = parent; - parent = curr->parent_pb; - } - return curr; - } - ///@brief Returns the tnode ID of the given atom's connected cluster pin tatum::NodeId find_tnode(const t_pb* atom, int cluster_pin_idx) { auto& atom_ctx = g_vpr_ctx.atom(); @@ -1806,6 +1809,19 @@ class NetlistWriterVisitor : public NetlistVisitor { return tnode_id; } + private: + ///@brief Returns the top complex block which contains the given pb + const t_pb* find_top_cb(const t_pb* curr) { + //Walk up through the pb graph until curr + //has no parent, at which point it will be the top pb + const t_pb* parent = curr->parent_pb; + while (parent != nullptr) { + curr = parent; + parent = curr->parent_pb; + } + return curr; + } + ///@brief Returns a LogicVec representing the LUT mask of the given LUT atom LogicVec load_lut_mask(size_t num_inputs, //LUT size const t_pb* atom) { //LUT primitive @@ -2063,13 +2079,15 @@ class NetlistWriterVisitor : public NetlistVisitor { return ::get_delay_ps(delay_sec); //Class overload hides file-scope by default } - private: //Data - std::string top_module_name_; /// inputs_; /// outputs_; /// assignments_; ///> cell_instances_; ///> logical_net_drivers_; @@ -2080,7 +2098,10 @@ class NetlistWriterVisitor : public NetlistVisitor { std::map logical_net_sink_delays_; //Output streams + protected: std::ostream& verilog_os_; + + private: std::ostream& blif_os_; std::ostream& sdf_os_; @@ -2091,11 +2112,192 @@ class NetlistWriterVisitor : public NetlistVisitor { struct t_analysis_opts opts_; }; +/** + * @brief A class which writes post-implementation merged netlists (Verilog) + * + * It implements the NetlistVisitor interface used by NetlistWalker (see netlist_walker.h) + */ +class MergedNetlistWriterVisitor : public NetlistWriterVisitor { + public: //Public interface + MergedNetlistWriterVisitor(std::ostream& verilog_os, /// delay_calc, + struct t_analysis_opts opts) + : NetlistWriterVisitor(verilog_os, blif_os, sdf_os, delay_calc, opts) {} + + std::map portmap; + + void visit_atom_impl(const t_pb* atom) override { + auto& atom_ctx = g_vpr_ctx.atom(); + + auto atom_pb = atom_ctx.lookup.pb_atom(atom); + if (atom_pb == AtomBlockId::INVALID()) { + return; + } + const t_model* model = atom_ctx.nlist.block_model(atom_pb); + + if (model->name == std::string(MODEL_INPUT)) { + auto merged_io_name = make_io(atom, PortType::INPUT); + if (merged_io_name != "") + inputs_.emplace_back(merged_io_name); + } else if (model->name == std::string(MODEL_OUTPUT)) { + auto merged_io_name = make_io(atom, PortType::OUTPUT); + if (merged_io_name != "") + outputs_.emplace_back(merged_io_name); + } else if (model->name == std::string(MODEL_NAMES)) { + cell_instances_.push_back(make_lut_instance(atom)); + } else if (model->name == std::string(MODEL_LATCH)) { + cell_instances_.push_back(make_latch_instance(atom)); + } else if (model->name == std::string("single_port_ram")) { + cell_instances_.push_back(make_ram_instance(atom)); + } else if (model->name == std::string("dual_port_ram")) { + cell_instances_.push_back(make_ram_instance(atom)); + } else if (model->name == std::string("multiply")) { + cell_instances_.push_back(make_multiply_instance(atom)); + } else if (model->name == std::string("adder")) { + cell_instances_.push_back(make_adder_instance(atom)); + } else { + cell_instances_.push_back(make_blackbox_instance(atom)); + } + } + + /** + * @brief Returns the name of circuit-level Input/Output ports with multi-bit + * ports merged into one. + * + * The I/O is recorded and instantiated by the top level output routines + * @param atom The implementation primitive representing the I/O + * @param dir The IO direction + * @param portmap Map for keeping port names and width + */ + std::string make_io(const t_pb* atom, + PortType dir) { + const t_pb_graph_node* pb_graph_node = atom->pb_graph_node; + + std::string io_name; + std::string indexed_io_name; + int cluster_pin_idx = -1; + // regex for matching 3 groups: + // * 'out:' - optional + // * verilog identifier - mandatory + // * index - optional + std::string rgx = "(out:)?([a-zA-Z$_]+[a-zA-Z0-9$_]*)(\\[[0-9]+\\])?$"; + std::string name(atom->name); + std::regex regex(rgx); + std::smatch matches; + + if (dir == PortType::INPUT) { + VTR_ASSERT(pb_graph_node->num_output_ports == 1); //One output port + VTR_ASSERT(pb_graph_node->num_output_pins[0] == 1); //One output pin + cluster_pin_idx = pb_graph_node->output_pins[0][0].pin_count_in_cluster; //Unique pin index in cluster + + io_name = ""; + indexed_io_name = atom->name; + + if (std::regex_match(name, matches, regex)) { + if (std::find(inputs_.begin(), inputs_.end(), matches[2]) == inputs_.end()) { //Skip already existing multi-bit port names + io_name = matches[2]; + portmap[matches[2]] = 0; + } else { + portmap[matches[2]]++; + } + } + + } else { + VTR_ASSERT(pb_graph_node->num_input_ports == 1); //One input port + VTR_ASSERT(pb_graph_node->num_input_pins[0] == 1); //One input pin + cluster_pin_idx = pb_graph_node->input_pins[0][0].pin_count_in_cluster; //Unique pin index in cluster + + //Strip off the starting 'out:' that vpr adds to uniqify outputs + //this makes the port names match the input blif file + + io_name = ""; + indexed_io_name = atom->name + 4; + + if (std::regex_search(name, matches, regex)) { + if (std::find(outputs_.begin(), outputs_.end(), matches[2]) == outputs_.end()) { //Skip already existing multi-bit port names + portmap[matches[2]] = 0; + io_name = matches[2]; + } else { + portmap[matches[2]]++; + } + } + } + + const auto& top_pb_route = find_top_pb_route(atom); + + if (top_pb_route.count(cluster_pin_idx)) { + //Net exists + auto atom_net_id = top_pb_route[cluster_pin_idx].atom_net_id; //Connected net in atom netlist + + //Port direction is inverted (inputs drive internal nets, outputs sink internal nets) + PortType wire_dir = (dir == PortType::INPUT) ? PortType::OUTPUT : PortType::INPUT; + + //Look up the tnode associated with this pin (used for delay calculation) + tatum::NodeId tnode_id = find_tnode(atom, cluster_pin_idx); + + auto wire_name = make_inst_wire(atom_net_id, tnode_id, indexed_io_name, wire_dir, 0, 0); + + //Connect the wires to to I/Os with assign statements + if (wire_dir == PortType::INPUT) { + assignments_.emplace_back(indexed_io_name, escape_verilog_identifier(wire_name)); + } else { + assignments_.emplace_back(escape_verilog_identifier(wire_name), indexed_io_name); + } + } + + return io_name; + } + + void print_primary_io(int depth) { + //Primary Inputs + for (auto iter = inputs_.begin(); iter != inputs_.end(); ++iter) { + //verilog_os_ << indent(depth + 1) << "input " << escape_verilog_identifier(*iter); + std::string range; + if (portmap[*iter] > 0) + verilog_os_ << indent(depth + 1) << "input [" << portmap[*iter] << ":0] " << *iter; + else + verilog_os_ << indent(depth + 1) << "input " << *iter; + if (iter + 1 != inputs_.end() || outputs_.size() > 0) { + verilog_os_ << ","; + } + verilog_os_ << "\n"; + } + + //Primary Outputs + for (auto iter = outputs_.begin(); iter != outputs_.end(); ++iter) { + std::string range; + if (portmap[*iter] > 0) + verilog_os_ << indent(depth + 1) << "output [" << portmap[*iter] << ":0] " << *iter; + else + verilog_os_ << indent(depth + 1) << "output " << *iter; + if (iter + 1 != outputs_.end()) { + verilog_os_ << ","; + } + verilog_os_ << "\n"; + } + } + + void print_assignments(int depth) { + verilog_os_ << "\n"; + verilog_os_ << indent(depth + 1) << "//IO assignments\n"; + for (auto& assign : assignments_) { + assign.print_merged_verilog(verilog_os_, indent(depth + 1)); + } + } + + void finish_impl() override { + // Don't write to blif and sdf streams + print_verilog(); + } +}; + // // Externally Accessible Functions // -///@brief Main routing for this file. See netlist_writer.h for details. +///@brief Main routine for this file. See netlist_writer.h for details. void netlist_writer(const std::string basename, std::shared_ptr delay_calc, struct t_analysis_opts opts) { std::string verilog_filename = basename + "_post_synthesis.v"; std::string blif_filename = basename + "_post_synthesis.blif"; @@ -2116,6 +2318,23 @@ void netlist_writer(const std::string basename, std::shared_ptr delay_calc, struct t_analysis_opts opts) { + std::string verilog_filename = basename + "_merged_post_implementation.v"; + + VTR_LOG("Writing Implementation Netlist: %s\n", verilog_filename.c_str()); + + std::ofstream verilog_os(verilog_filename); + // Don't write blif and sdf, pass dummy streams + std::ofstream blif_os; + std::ofstream sdf_os; + + MergedNetlistWriterVisitor visitor(verilog_os, blif_os, sdf_os, delay_calc, opts); + + NetlistWalker nl_walker(visitor); + + nl_walker.walk(); +} // // File-scope function implementations // diff --git a/vpr/src/base/netlist_writer.h b/vpr/src/base/netlist_writer.h index 9c4306de7..b3c7fd1cb 100644 --- a/vpr/src/base/netlist_writer.h +++ b/vpr/src/base/netlist_writer.h @@ -17,4 +17,14 @@ */ void netlist_writer(const std::string basename, std::shared_ptr delay_calc, struct t_analysis_opts opts); + +/** + * @brief Writes out the post implementation netlist in Verilog format. + * It has its top module ports merged into multi-bit ones. + * + * Written filename ends in {basename}_merged_post_implementation.v where {basename} is the + * basename argument. + */ +void merged_netlist_writer(const std::string basename, std::shared_ptr delay_calc, struct t_analysis_opts opts); + #endif diff --git a/vpr/src/base/read_options.cpp b/vpr/src/base/read_options.cpp index 0e0af27f4..6dbf52ee7 100644 --- a/vpr/src/base/read_options.cpp +++ b/vpr/src/base/read_options.cpp @@ -1725,6 +1725,13 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg .default_value("off") .show_in(argparse::ShowIn::HELP_ONLY); + analysis_grp.add_argument(args.Generate_Post_Implementation_Merged_Netlist, "--gen_post_implementation_merged_netlist") + .help( + "Generates the post-implementation netlist with merged top module ports" + " Used for post-implementation simulation and verification") + .default_value("off") + .show_in(argparse::ShowIn::HELP_ONLY); + analysis_grp.add_argument(args.timing_report_npaths, "--timing_report_npaths") .help("Controls how many timing paths are reported.") .default_value("100") diff --git a/vpr/src/base/read_options.h b/vpr/src/base/read_options.h index a4ee70993..66e522719 100644 --- a/vpr/src/base/read_options.h +++ b/vpr/src/base/read_options.h @@ -156,6 +156,7 @@ struct t_options { /* Analysis options */ argparse::ArgValue full_stats; argparse::ArgValue Generate_Post_Synthesis_Netlist; + argparse::ArgValue Generate_Post_Implementation_Merged_Netlist; argparse::ArgValue timing_report_npaths; argparse::ArgValue timing_report_detail; argparse::ArgValue timing_report_skew; diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index 266c8ba9b..ccf58d766 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -1199,6 +1199,11 @@ void vpr_analysis(t_vpr_setup& vpr_setup, const t_arch& Arch, const RouteStatus& vpr_setup.AnalysisOpts); } + //Write the post-implementation merged netlist + if (vpr_setup.AnalysisOpts.gen_post_implementation_merged_netlist) { + merged_netlist_writer(atom_ctx.nlist.netlist_name().c_str(), analysis_delay_calc, vpr_setup.AnalysisOpts); + } + //Do power analysis if (vpr_setup.PowerOpts.do_power) { vpr_power_estimation(vpr_setup, Arch, *timing_info, route_status); diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index 13a7aa2f3..24da8962d 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -966,6 +966,7 @@ struct t_analysis_opts { e_stage_action doAnalysis; bool gen_post_synthesis_netlist; + bool gen_post_implementation_merged_netlist; e_post_synth_netlist_unconn_handling post_synth_netlist_unconn_input_handling; e_post_synth_netlist_unconn_handling post_synth_netlist_unconn_output_handling; From 1677ac0ddb1482bc12bb0db6c0ebfd6a4d9ec419 Mon Sep 17 00:00:00 2001 From: coolbreeze413 Date: Thu, 30 Jun 2022 18:06:32 +0530 Subject: [PATCH 08/14] fix count of ',' logic and clear stringstream for string to int conversion --- vpr/src/base/read_route.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vpr/src/base/read_route.cpp b/vpr/src/base/read_route.cpp index 6688db005..bf1d78f51 100644 --- a/vpr/src/base/read_route.cpp +++ b/vpr/src/base/read_route.cpp @@ -423,7 +423,7 @@ static void format_ptc_num(std::vector& ptc_nums, std::string ptc_str, Clus // detect and remove the parenthesis openfpga::StringToken tokenizer0(ptc_str); std::vector tokens0 = tokenizer0.split(','); - size_t ptc_count = tokens0.size() + 1; + size_t ptc_count = tokens0.size(); openfpga::StringToken tokenizer1(ptc_count > 1? format_name(ptc_str) : ptc_str); // now do the real job @@ -431,6 +431,7 @@ static void format_ptc_num(std::vector& ptc_nums, std::string ptc_str, Clus std::stringstream ptc_stream; int num; for (size_t i = 0; i < tokens1.size(); i++) { + ptc_stream.clear(); ptc_stream << tokens1[i]; ptc_stream >> num; if (ptc_stream.fail()) { From 4424988712c70e92d60c86bd31f100efee368c21 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 1 Jul 2022 00:02:42 +0000 Subject: [PATCH 09/14] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index 9b2d076f7..fa98130fa 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.1.282 +1.1.296 From 4e45f31a42efbec7fc072d0be1d79df58259101a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Jul 2022 06:36:34 +0000 Subject: [PATCH 10/14] Bump yosys-plugins from `75df29e` to `6bc9630` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `75df29e` to `6bc9630`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/75df29e1c68353d9c9b5b3db7f4748e057d3d6a1...6bc9630fb7fb7527cadbb696eacbb17a6d4dc347) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index 75df29e1c..6bc9630fb 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 75df29e1c68353d9c9b5b3db7f4748e057d3d6a1 +Subproject commit 6bc9630fb7fb7527cadbb696eacbb17a6d4dc347 From 3c7aecec9fcdc78fb7240b2957b231f899ac6223 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 2 Jul 2022 00:02:24 +0000 Subject: [PATCH 11/14] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index fa98130fa..bed9ce916 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.1.296 +1.1.300 From 519f1cb97358789309ec67c389387b7af2bd2c48 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Jul 2022 06:58:07 +0000 Subject: [PATCH 12/14] Bump yosys-plugins from `6bc9630` to `d149693` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `6bc9630` to `d149693`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/6bc9630fb7fb7527cadbb696eacbb17a6d4dc347...d1496936c14de0c425f7071d498c0662e9a1bff7) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index 6bc9630fb..d1496936c 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit 6bc9630fb7fb7527cadbb696eacbb17a6d4dc347 +Subproject commit d1496936c14de0c425f7071d498c0662e9a1bff7 From 955219da1469c16781f11054c1f3d82ac5bda30c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 8 Jul 2022 00:02:41 +0000 Subject: [PATCH 13/14] Updated Patch Count --- VERSION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.md b/VERSION.md index bed9ce916..0a37e6085 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -1.1.300 +1.1.304 From 8612ee6efa445292b57772f87991c9cfd4a57df4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Jul 2022 06:31:00 +0000 Subject: [PATCH 14/14] Bump yosys-plugins from `d149693` to `8aa193b` Bumps [yosys-plugins](https://github.com/SymbiFlow/yosys-symbiflow-plugins) from `d149693` to `8aa193b`. - [Release notes](https://github.com/SymbiFlow/yosys-symbiflow-plugins/releases) - [Commits](https://github.com/SymbiFlow/yosys-symbiflow-plugins/compare/d1496936c14de0c425f7071d498c0662e9a1bff7...8aa193b5a06a8125169534853c6f723914e21e9d) --- updated-dependencies: - dependency-name: yosys-plugins dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yosys-plugins | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yosys-plugins b/yosys-plugins index d1496936c..8aa193b5a 160000 --- a/yosys-plugins +++ b/yosys-plugins @@ -1 +1 @@ -Subproject commit d1496936c14de0c425f7071d498c0662e9a1bff7 +Subproject commit 8aa193b5a06a8125169534853c6f723914e21e9d