3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-06-08 15:13:24 +00:00

Add support for SystemVerilog-style `define to Verilog frontend

This patch should support things like

  `define foo(a, b = 3, c)   a+b+c

  `foo(1, ,2)

which will evaluate to 1+3+2. It also spots mistakes like

  `foo(1)

(the 3rd argument doesn't have a default value, so a call site is
required to set it).

Most of the patch is a simple parser for the format in preproc.cc, but
I've also taken the opportunity to wrap up the "name -> definition"
map in a type, rather than use multiple std::map's.

Since this type needs to be visible to code that touches defines, I've
pulled it (and the frontend_verilog_preproc declaration) out into a
new file at frontends/verilog/preproc.h and included that where
necessary.

Finally, the patch adds a few tests in tests/various to check that we
are parsing everything correctly.
This commit is contained in:
Rupert Swarbrick 2020-03-17 09:34:31 +00:00 committed by Rupert Swarbrick
parent 4c38895fab
commit 044ca9dde4
11 changed files with 636 additions and 151 deletions

View file

@ -27,6 +27,7 @@
*/
#include "verilog_frontend.h"
#include "preproc.h"
#include "kernel/yosys.h"
#include "libs/sha1/sha1.h"
#include <stdarg.h>
@ -253,7 +254,8 @@ struct VerilogFrontend : public Frontend {
bool flag_defer = false;
bool flag_noblackbox = false;
bool flag_nowb = false;
std::map<std::string, std::string> defines_map;
define_map_t defines_map;
std::list<std::string> include_dirs;
std::list<std::string> attributes;
@ -369,7 +371,7 @@ struct VerilogFrontend : public Frontend {
}
if (arg == "-lib") {
lib_mode = true;
defines_map["BLACKBOX"] = string();
defines_map.add("BLACKBOX", "");
continue;
}
if (arg == "-nowb") {
@ -421,7 +423,7 @@ struct VerilogFrontend : public Frontend {
value = name.substr(equal+1);
name = name.substr(0, equal);
}
defines_map[name] = value;
defines_map.add(name, value);
continue;
}
if (arg.compare(0, 2, "-D") == 0) {
@ -430,7 +432,7 @@ struct VerilogFrontend : public Frontend {
std::string value;
if (equal != std::string::npos)
value = arg.substr(equal+1);
defines_map[name] = value;
defines_map.add(name, value);
continue;
}
if (arg == "-I" && argidx+1 < args.size()) {
@ -460,7 +462,7 @@ struct VerilogFrontend : public Frontend {
std::string code_after_preproc;
if (!flag_nopp) {
code_after_preproc = frontend_verilog_preproc(*f, filename, defines_map, design->verilog_defines, include_dirs);
code_after_preproc = frontend_verilog_preproc(*f, filename, defines_map, *design->verilog_defines, include_dirs);
if (flag_ppdump)
log("-- Verilog code after preprocessor --\n%s-- END OF DUMP --\n", code_after_preproc.c_str());
lexin = new std::istringstream(code_after_preproc);
@ -592,7 +594,7 @@ struct VerilogDefines : public Pass {
value = name.substr(equal+1);
name = name.substr(0, equal);
}
design->verilog_defines[name] = std::pair<std::string, bool>(value, false);
design->verilog_defines->add(name, value);
continue;
}
if (arg.compare(0, 2, "-D") == 0) {
@ -601,27 +603,25 @@ struct VerilogDefines : public Pass {
std::string value;
if (equal != std::string::npos)
value = arg.substr(equal+1);
design->verilog_defines[name] = std::pair<std::string, bool>(value, false);
design->verilog_defines->add(name, value);
continue;
}
if (arg == "-U" && argidx+1 < args.size()) {
std::string name = args[++argidx];
design->verilog_defines.erase(name);
design->verilog_defines->erase(name);
continue;
}
if (arg.compare(0, 2, "-U") == 0) {
std::string name = arg.substr(2);
design->verilog_defines.erase(name);
design->verilog_defines->erase(name);
continue;
}
if (arg == "-reset") {
design->verilog_defines.clear();
design->verilog_defines->clear();
continue;
}
if (arg == "-list") {
for (auto &it : design->verilog_defines) {
log("`define %s%s %s\n", it.first.c_str(), it.second.second ? "()" : "", it.second.first.c_str());
}
design->verilog_defines->log();
continue;
}
break;