Merge pull request #417 from antmicro/rk/defaults-defines
Add systemverilog_defines, systemverilog_defaults
diff --git a/systemverilog-plugin/tests/Makefile b/systemverilog-plugin/tests/Makefile
index 1843a05..849a9f9 100644
--- a/systemverilog-plugin/tests/Makefile
+++ b/systemverilog-plugin/tests/Makefile
@@ -18,7 +18,9 @@
break_continue \
separate-compilation \
debug-flag \
- report-flag
+ report-flag \
+ defines \
+ defaults
include $(shell pwd)/../../Makefile_test.common
@@ -27,3 +29,5 @@
separate-compilation_verify = true
debug-flag_verify = true
report-flag_verify = true
+defaults_verify = true
+defines_verify = true
diff --git a/systemverilog-plugin/tests/defaults/defaults.tcl b/systemverilog-plugin/tests/defaults/defaults.tcl
new file mode 100644
index 0000000..a363895
--- /dev/null
+++ b/systemverilog-plugin/tests/defaults/defaults.tcl
@@ -0,0 +1,23 @@
+yosys -import
+if { [info procs read_uhdm] == {} } { plugin -i systemverilog }
+yosys -import ;# ingest plugin commands
+
+set TMP_DIR /tmp
+if { [info exists ::env(TMPDIR) ] } {
+ set TMP_DIR $::env(TMPDIR)
+}
+
+# Define forbidden value
+systemverilog_defaults -add -DPAKALA
+# Stash it
+systemverilog_defaults -push
+systemverilog_defaults -clear
+read_systemverilog $::env(DESIGN_TOP).v
+# Allow parsing the module again
+delete top
+systemverilog_defaults -pop
+# Skip check for forbidden value
+systemverilog_defaults -add -Pbypass=1
+read_systemverilog $::env(DESIGN_TOP).v
+hierarchy
+write_verilog
diff --git a/systemverilog-plugin/tests/defaults/defaults.v b/systemverilog-plugin/tests/defaults/defaults.v
new file mode 100644
index 0000000..f565a77
--- /dev/null
+++ b/systemverilog-plugin/tests/defaults/defaults.v
@@ -0,0 +1,28 @@
+// Copyright 2020-2022 F4PGA Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+module top #(
+ parameter bit bypass = 0
+)(
+ input clk,
+ output out
+);
+
+`ifdef PAKALA
+ initial if(!bypass) $stop("Defined forbidden value");
+`endif
+ assign out = clk;
+endmodule
diff --git a/systemverilog-plugin/tests/defines/defines.tcl b/systemverilog-plugin/tests/defines/defines.tcl
new file mode 100644
index 0000000..030c1ad
--- /dev/null
+++ b/systemverilog-plugin/tests/defines/defines.tcl
@@ -0,0 +1,15 @@
+yosys -import
+if { [info procs read_uhdm] == {} } { plugin -i systemverilog }
+yosys -import ;# ingest plugin commands
+
+set TMP_DIR /tmp
+if { [info exists ::env(TMPDIR) ] } {
+ set TMP_DIR $::env(TMPDIR)
+}
+
+systemverilog_defines -DPONA
+systemverilog_defines -DPAKALA
+systemverilog_defines -UPAKALA
+read_systemverilog $::env(DESIGN_TOP).v
+hierarchy
+write_verilog
diff --git a/systemverilog-plugin/tests/defines/defines.v b/systemverilog-plugin/tests/defines/defines.v
new file mode 100644
index 0000000..528e9f1
--- /dev/null
+++ b/systemverilog-plugin/tests/defines/defines.v
@@ -0,0 +1,29 @@
+// Copyright 2020-2022 F4PGA Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+module top (
+ input clk,
+ output out
+);
+
+`ifndef PONA
+ initial $stop("Define failed");
+`endif
+`ifdef PAKALA
+ initial $stop("Undefine failed");
+`endif
+ assign out = clk;
+endmodule
diff --git a/systemverilog-plugin/uhdmsurelogastfrontend.cc b/systemverilog-plugin/uhdmsurelogastfrontend.cc
index c11c861..3c1c2f6 100644
--- a/systemverilog-plugin/uhdmsurelogastfrontend.cc
+++ b/systemverilog-plugin/uhdmsurelogastfrontend.cc
@@ -31,6 +31,8 @@
#endif
#include <memory>
+#include <list>
+
#include "Surelog/ErrorReporting/Report.h"
#include "Surelog/surelog.h"
@@ -42,6 +44,13 @@
YOSYS_NAMESPACE_BEGIN
+// Store systemverilog defaults to be passed for every invocation of read_systemverilog
+static std::vector<std::string> systemverilog_defaults;
+static std::list<std::vector<std::string>> systemverilog_defaults_stack;
+
+// Store global definitions for top-level defines
+static std::vector<std::string> systemverilog_defines;
+
// SURELOG::scompiler wrapper.
// Owns UHDM/VPI resources used by designs returned from `execute`
class Compiler
@@ -119,9 +128,29 @@
AST::AstNode *parse(std::string filename) override
{
std::vector<const char *> cstrings;
- cstrings.reserve(this->args.size());
- for (size_t i = 0; i < this->args.size(); ++i)
+ bool link = false;
+ cstrings.reserve(this->args.size() + systemverilog_defaults.size() + systemverilog_defines.size());
+ for (size_t i = 0; i < this->args.size(); ++i) {
cstrings.push_back(const_cast<char *>(this->args[i].c_str()));
+ if (this->args[i] == "-link")
+ link = true;
+ }
+
+ if (!link) {
+ // Add systemverilog defaults args
+ for (size_t i = 0; i < systemverilog_defaults.size(); ++i) {
+ // Convert args to surelog compatible
+ if (systemverilog_defaults[i] == "-defer")
+ this->shared.defer = true;
+ // Pass any remainings args directly to surelog
+ else
+ cstrings.push_back(const_cast<char *>(systemverilog_defaults[i].c_str()));
+ }
+
+ // Add systemverilog defines args
+ for (size_t i = 0; i < systemverilog_defines.size(); ++i)
+ cstrings.push_back(const_cast<char *>(systemverilog_defines[i].c_str()));
+ }
auto symbolTable = std::make_unique<SURELOG::SymbolTable>();
auto errors = std::make_unique<SURELOG::ErrorContainer>(symbolTable.get());
@@ -182,6 +211,9 @@
this->shared.report.write(this->report_directory);
}
+ // FIXME: Check and reset remaining shared data
+ this->shared.top_nodes.clear();
+ this->shared.nonSynthesizableObjects.clear();
return current_ast;
}
void call_log_header(RTLIL::Design *design) override { log_header(design, "Executing Verilog with UHDM frontend.\n"); }
@@ -198,7 +230,164 @@
log("Read SystemVerilog files using Surelog into the current design\n");
log("\n");
this->print_read_options();
+ log(" -Ipath\n");
+ log(" add include path.\n");
+ log("\n");
+ log(" -Pparameter=value\n");
+ log(" define parameter as value.\n");
+ log("\n");
}
} UhdmSystemVerilogFrontend;
+struct SystemVerilogDefaults : public Pass {
+ SystemVerilogDefaults() : Pass("systemverilog_defaults", "set default options for read_systemverilog") {}
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" systemverilog_defaults -add [options]\n");
+ log("\n");
+ log("Add the specified options to the list of default options to read_systemverilog.\n");
+ log("\n");
+ log("\n");
+ log(" systemverilog_defaults -clear\n");
+ log("\n");
+ log("Clear the list of Systemverilog default options.\n");
+ log("\n");
+ log("\n");
+ log(" systemverilog_defaults -push\n");
+ log(" systemverilog_defaults -pop\n");
+ log("\n");
+ log("Push or pop the list of default options to a stack. Note that -push does\n");
+ log("not imply -clear.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *) override
+ {
+ if (args.size() < 2)
+ cmd_error(args, 1, "Missing argument.");
+
+ if (args[1] == "-add") {
+ systemverilog_defaults.insert(systemverilog_defaults.end(), args.begin() + 2, args.end());
+ return;
+ }
+
+ if (args.size() != 2)
+ cmd_error(args, 2, "Extra argument.");
+
+ if (args[1] == "-clear") {
+ systemverilog_defaults.clear();
+ return;
+ }
+
+ if (args[1] == "-push") {
+ systemverilog_defaults_stack.push_back(systemverilog_defaults);
+ return;
+ }
+
+ if (args[1] == "-pop") {
+ if (systemverilog_defaults_stack.empty()) {
+ systemverilog_defaults.clear();
+ } else {
+ systemverilog_defaults.swap(systemverilog_defaults_stack.back());
+ systemverilog_defaults_stack.pop_back();
+ }
+ return;
+ }
+ }
+} SystemVerilogDefaults;
+
+struct SystemVerilogDefines : public Pass {
+ SystemVerilogDefines() : Pass("systemverilog_defines", "define and undefine systemverilog defines")
+ {
+ systemverilog_defines.push_back("-DYOSYS=1");
+ }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" systemverilog_defines [options]\n");
+ log("\n");
+ log("Define and undefine systemverilog preprocessor macros.\n");
+ log("\n");
+ log(" -Dname[=definition]\n");
+ log(" define the preprocessor symbol 'name' and set its optional value\n");
+ log(" 'definition'\n");
+ log("\n");
+ log(" -Uname[=definition]\n");
+ log(" undefine the preprocessor symbol 'name'\n");
+ log("\n");
+ log(" -reset\n");
+ log(" clear list of defined preprocessor symbols\n");
+ log("\n");
+ log(" -list\n");
+ log(" list currently defined preprocessor symbols\n");
+ log("\n");
+ }
+ void remove(const std::string name)
+ {
+ auto it = systemverilog_defines.begin();
+ while (it != systemverilog_defines.end()) {
+ std::string nm;
+ size_t equal = (*it).find('=', 2);
+ if (equal == std::string::npos)
+ nm = (*it).substr(2, std::string::npos);
+ else
+ nm = (*it).substr(2, equal - 2);
+ if (name == nm)
+ systemverilog_defines.erase(it);
+ else
+ it++;
+ }
+ }
+ void dump(void)
+ {
+ for (size_t i = 0; i < systemverilog_defines.size(); ++i) {
+ std::string name, value = "";
+ size_t equal = systemverilog_defines[i].find('=', 2);
+ name = systemverilog_defines[i].substr(2, equal - 2);
+ if (equal != std::string::npos)
+ value = systemverilog_defines[i].substr(equal + 1, std::string::npos);
+ Yosys::log("`define %s %s\n", name.c_str(), value.c_str());
+ }
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ std::string arg = args[argidx];
+ if (arg == "-D" && argidx + 1 < args.size()) {
+ systemverilog_defines.push_back("-D" + args[++argidx]);
+ continue;
+ }
+ if (arg.compare(0, 2, "-D") == 0) {
+ systemverilog_defines.push_back(arg);
+ continue;
+ }
+ if (arg == "-U" && argidx + 1 < args.size()) {
+ std::string name = args[++argidx];
+ this->remove(name);
+ continue;
+ }
+ if (arg.compare(0, 2, "-U") == 0) {
+ std::string name = arg.substr(2);
+ this->remove(name);
+ continue;
+ }
+ if (arg == "-reset") {
+ systemverilog_defines.erase(systemverilog_defines.begin() + 1, systemverilog_defines.end());
+ continue;
+ }
+ if (arg == "-list") {
+ this->dump();
+ continue;
+ }
+ break;
+ }
+
+ if (args.size() != argidx)
+ cmd_error(args, argidx, "Extra argument.");
+ }
+} SystemVerilogDefines;
+
YOSYS_NAMESPACE_END