aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/verilog
diff options
context:
space:
mode:
authorAhmed Irfan <irfan@levert.(none)>2015-04-03 16:38:07 +0200
committerAhmed Irfan <irfan@levert.(none)>2015-04-03 16:38:07 +0200
commitbdf6b2b19ab2206f5957ad5b2ec582c2730d45ee (patch)
tree1d02541701054a1c3b1cdb66478d0cbc31c2d38f /frontends/verilog
parent8acdd90bc918b780ad45cdac42b3baf84d2cc476 (diff)
parent4b4490761949e738dee54bdfc52e080e0a5c9067 (diff)
downloadyosys-bdf6b2b19ab2206f5957ad5b2ec582c2730d45ee.tar.gz
yosys-bdf6b2b19ab2206f5957ad5b2ec582c2730d45ee.tar.bz2
yosys-bdf6b2b19ab2206f5957ad5b2ec582c2730d45ee.zip
Merge branch 'master' of https://github.com/cliffordwolf/yosys
Diffstat (limited to 'frontends/verilog')
-rw-r--r--frontends/verilog/.gitignore8
-rw-r--r--frontends/verilog/Makefile.inc24
-rw-r--r--frontends/verilog/const2ast.cc16
-rw-r--r--frontends/verilog/preproc.cc9
-rw-r--r--frontends/verilog/verilog_frontend.cc60
-rw-r--r--frontends/verilog/verilog_frontend.h5
-rw-r--r--frontends/verilog/verilog_lexer.l (renamed from frontends/verilog/lexer.l)51
-rw-r--r--frontends/verilog/verilog_parser.y (renamed from frontends/verilog/parser.y)136
8 files changed, 220 insertions, 89 deletions
diff --git a/frontends/verilog/.gitignore b/frontends/verilog/.gitignore
index 72b06b0bf..1d4ae9e5c 100644
--- a/frontends/verilog/.gitignore
+++ b/frontends/verilog/.gitignore
@@ -1,4 +1,4 @@
-lexer.cc
-parser.output
-parser.tab.cc
-parser.tab.h
+verilog_lexer.cc
+verilog_parser.output
+verilog_parser.tab.cc
+verilog_parser.tab.h
diff --git a/frontends/verilog/Makefile.inc b/frontends/verilog/Makefile.inc
index 49eb320ec..92cbd0b87 100644
--- a/frontends/verilog/Makefile.inc
+++ b/frontends/verilog/Makefile.inc
@@ -1,20 +1,20 @@
-GENFILES += frontends/verilog/parser.tab.cc
-GENFILES += frontends/verilog/parser.tab.h
-GENFILES += frontends/verilog/parser.output
-GENFILES += frontends/verilog/lexer.cc
+GENFILES += frontends/verilog/verilog_parser.tab.cc
+GENFILES += frontends/verilog/verilog_parser.tab.h
+GENFILES += frontends/verilog/verilog_parser.output
+GENFILES += frontends/verilog/verilog_lexer.cc
-frontends/verilog/parser.tab.cc: frontends/verilog/parser.y
- $(P) bison -d -r all -b frontends/verilog/parser frontends/verilog/parser.y
- $(Q) mv frontends/verilog/parser.tab.c frontends/verilog/parser.tab.cc
+frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y
+ $(P) $(BISON) -d -r all -b frontends/verilog/verilog_parser frontends/verilog/verilog_parser.y
+ $(Q) mv frontends/verilog/verilog_parser.tab.c frontends/verilog/verilog_parser.tab.cc
-frontends/verilog/parser.tab.h: frontends/verilog/parser.tab.cc
+frontends/verilog/verilog_parser.tab.h: frontends/verilog/verilog_parser.tab.cc
-frontends/verilog/lexer.cc: frontends/verilog/lexer.l
- $(P) flex -o frontends/verilog/lexer.cc frontends/verilog/lexer.l
+frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l
+ $(P) flex -o frontends/verilog/verilog_lexer.cc frontends/verilog/verilog_lexer.l
-OBJS += frontends/verilog/parser.tab.o
-OBJS += frontends/verilog/lexer.o
+OBJS += frontends/verilog/verilog_parser.tab.o
+OBJS += frontends/verilog/verilog_lexer.o
OBJS += frontends/verilog/preproc.o
OBJS += frontends/verilog/verilog_frontend.o
OBJS += frontends/verilog/const2ast.o
diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc
index a81e3010f..735bc5f99 100644
--- a/frontends/verilog/const2ast.cc
+++ b/frontends/verilog/const2ast.cc
@@ -132,8 +132,16 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
}
// convert the verilog code for a constant to an AST node
-AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type)
+AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn_z)
{
+ if (warn_z) {
+ AstNode *ret = const2ast(code, case_type);
+ if (std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end())
+ log_warning("Yosys does not support tri-state logic at the moment. (%s:%d)\n",
+ current_filename.c_str(), frontend_verilog_yyget_lineno());
+ return ret;
+ }
+
const char *str = code.c_str();
// Strings
@@ -174,7 +182,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type)
if (str == endptr)
len_in_bits = -1;
- // The "<bits>'s?[bodh]<digits>" syntax
+ // The "<bits>'s?[bodhBODH]<digits>" syntax
if (*endptr == '\'')
{
std::vector<RTLIL::State> data;
@@ -186,15 +194,19 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type)
switch (*(endptr+1))
{
case 'b':
+ case 'B':
my_strtobin(data, endptr+2, len_in_bits, 2, case_type);
break;
case 'o':
+ case 'O':
my_strtobin(data, endptr+2, len_in_bits, 8, case_type);
break;
case 'd':
+ case 'D':
my_strtobin(data, endptr+2, len_in_bits, 10, case_type);
break;
case 'h':
+ case 'H':
my_strtobin(data, endptr+2, len_in_bits, 16, case_type);
break;
default:
diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc
index f83433219..e2118630e 100644
--- a/frontends/verilog/preproc.cc
+++ b/frontends/verilog/preproc.cc
@@ -201,8 +201,8 @@ static void input_file(std::istream &f, std::string filename)
insert_input("");
auto it = input_buffer.begin();
- input_buffer.insert(it, "`file_push " + filename + "\n");
- while ((rc = f.readsome(buffer, sizeof(buffer)-1)) > 0) {
+ input_buffer.insert(it, "`file_push \"" + filename + "\"\n");
+ while ((rc = readsome(f, buffer, sizeof(buffer)-1)) > 0) {
buffer[rc] = 0;
input_buffer.insert(it, buffer);
}
@@ -221,7 +221,8 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
input_buffer_charp = 0;
input_file(f, filename);
- defines_map["__YOSYS__"] = "1";
+ defines_map["YOSYS"] = "1";
+ defines_map["SYNTHESIS"] = "1";
while (!input_buffer.empty())
{
@@ -422,7 +423,7 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons
if (tok == "(" || tok == "{" || tok == "[")
level++;
}
- for (size_t i = 0; i < args.size(); i++)
+ for (int i = 0; i < GetSize(args); i++)
defines_map[stringf("macro_%s_arg%d", name.c_str(), i+1)] = args[i];
} else {
insert_input(tok);
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index c6d4a0b79..635c9ce47 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -54,6 +54,10 @@ struct VerilogFrontend : public Frontend {
log(" enable support for SystemVerilog features. (only a small subset\n");
log(" of SystemVerilog is supported)\n");
log("\n");
+ log(" -formal\n");
+ log(" enable support for assert() and assume() statements\n");
+ log(" (assert support is also enabled with -sv)\n");
+ log("\n");
log(" -dump_ast1\n");
log(" dump abstract syntax tree (before simplification)\n");
log("\n");
@@ -83,11 +87,20 @@ struct VerilogFrontend : public Frontend {
log(" this can also be achieved by setting the 'nomem2reg'\n");
log(" attribute on the respective module or register.\n");
log("\n");
+ log(" This is potentially dangerous. Usually the front-end has good\n");
+ log(" reasons for converting an array to a list of registers.\n");
+ log(" Prohibiting this step will likely result in incorrect synthesis\n");
+ log(" results.\n");
+ log("\n");
log(" -mem2reg\n");
log(" always convert memories to registers. this can also be\n");
log(" achieved by setting the 'mem2reg' attribute on the respective\n");
log(" module or register.\n");
log("\n");
+ log(" -nomeminit\n");
+ log(" do not infer $meminit cells and instead convert initialized\n");
+ log(" memories to registers directly in the front-end.\n");
+ log("\n");
log(" -ppdump\n");
log(" dump verilog code after pre-processor\n");
log("\n");
@@ -139,6 +152,7 @@ struct VerilogFrontend : public Frontend {
bool flag_dump_ast2 = false;
bool flag_dump_vlog = false;
bool flag_nolatches = false;
+ bool flag_nomeminit = false;
bool flag_nomem2reg = false;
bool flag_mem2reg = false;
bool flag_ppdump = false;
@@ -154,6 +168,7 @@ struct VerilogFrontend : public Frontend {
frontend_verilog_yydebug = false;
sv_mode = false;
+ formal_mode = false;
log_header("Executing Verilog-2005 frontend.\n");
@@ -166,6 +181,10 @@ struct VerilogFrontend : public Frontend {
sv_mode = true;
continue;
}
+ if (arg == "-formal") {
+ formal_mode = true;
+ continue;
+ }
if (arg == "-dump_ast1") {
flag_dump_ast1 = true;
continue;
@@ -186,6 +205,10 @@ struct VerilogFrontend : public Frontend {
flag_nolatches = true;
continue;
}
+ if (arg == "-nomeminit") {
+ flag_nomeminit = true;
+ continue;
+ }
if (arg == "-nomem2reg") {
flag_nomem2reg = true;
continue;
@@ -257,7 +280,8 @@ struct VerilogFrontend : public Frontend {
}
extra_args(f, filename, args, argidx);
- log("Parsing Verilog input from `%s' to AST representation.\n", filename.c_str());
+ log("Parsing %s%s input from `%s' to AST representation.\n",
+ formal_mode ? "formal " : "", sv_mode ? "SystemVerilog" : "Verilog", filename.c_str());
AST::current_filename = filename;
AST::set_line_num = &frontend_verilog_yyset_lineno;
@@ -288,7 +312,7 @@ struct VerilogFrontend : public Frontend {
child->attributes[attr] = AST::AstNode::mkconst_int(1, false);
}
- AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_ignore_redef, flag_defer, default_nettype_wire);
+ AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_ignore_redef, flag_defer, default_nettype_wire);
if (!flag_nopp)
delete lexin;
@@ -300,22 +324,6 @@ struct VerilogFrontend : public Frontend {
}
} VerilogFrontend;
-// the yyerror function used by bison to report parser errors
-void frontend_verilog_yyerror(char const *fmt, ...)
-{
- va_list ap;
- char buffer[1024];
- char *p = buffer;
- p += snprintf(p, buffer + sizeof(buffer) - p, "Parser error in line %s:%d: ",
- AST::current_filename.c_str(), frontend_verilog_yyget_lineno());
- va_start(ap, fmt);
- p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap);
- va_end(ap);
- p += snprintf(p, buffer + sizeof(buffer) - p, "\n");
- log_error("%s", buffer);
- exit(1);
-}
-
struct VerilogDefaults : public Pass {
VerilogDefaults() : Pass("verilog_defaults", "set default options for read_verilog") { }
virtual void help()
@@ -376,3 +384,19 @@ struct VerilogDefaults : public Pass {
YOSYS_NAMESPACE_END
+// the yyerror function used by bison to report parser errors
+void frontend_verilog_yyerror(char const *fmt, ...)
+{
+ va_list ap;
+ char buffer[1024];
+ char *p = buffer;
+ p += snprintf(p, buffer + sizeof(buffer) - p, "Parser error in line %s:%d: ",
+ YOSYS_NAMESPACE_PREFIX AST::current_filename.c_str(), frontend_verilog_yyget_lineno());
+ va_start(ap, fmt);
+ p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap);
+ va_end(ap);
+ p += snprintf(p, buffer + sizeof(buffer) - p, "\n");
+ YOSYS_NAMESPACE_PREFIX log_error("%s", buffer);
+ exit(1);
+}
+
diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h
index af6495f8f..5561f54cd 100644
--- a/frontends/verilog/verilog_frontend.h
+++ b/frontends/verilog/verilog_frontend.h
@@ -43,7 +43,7 @@ namespace VERILOG_FRONTEND
extern struct AST::AstNode *current_ast;
// this function converts a Verilog constant to an AST_CONSTANT node
- AST::AstNode *const2ast(std::string code, char case_type = 0);
+ AST::AstNode *const2ast(std::string code, char case_type = 0, bool warn_z = false);
// state of `default_nettype
extern bool default_nettype_wire;
@@ -51,6 +51,9 @@ namespace VERILOG_FRONTEND
// running in SystemVerilog mode
extern bool sv_mode;
+ // running in -formal mode
+ extern bool formal_mode;
+
// lexer input stream
extern std::istream *lexin;
}
diff --git a/frontends/verilog/lexer.l b/frontends/verilog/verilog_lexer.l
index c9302aba8..8fbaa953d 100644
--- a/frontends/verilog/lexer.l
+++ b/frontends/verilog/verilog_lexer.l
@@ -42,7 +42,7 @@
#include "kernel/log.h"
#include "verilog_frontend.h"
#include "frontends/ast/ast.h"
-#include "parser.tab.h"
+#include "verilog_parser.tab.h"
USING_YOSYS_NAMESPACE
using namespace AST;
@@ -64,7 +64,7 @@ YOSYS_NAMESPACE_END
return TOK_ID;
#define YY_INPUT(buf,result,max_size) \
- result = lexin->readsome(buf, max_size);
+ result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size)
%}
@@ -85,6 +85,10 @@ YOSYS_NAMESPACE_END
fn_stack.push_back(current_filename);
ln_stack.push_back(frontend_verilog_yyget_lineno());
current_filename = yytext+11;
+ if (!current_filename.empty() && current_filename.front() == '"')
+ current_filename = current_filename.substr(1);
+ if (!current_filename.empty() && current_filename.back() == '"')
+ current_filename = current_filename.substr(0, current_filename.size()-1);
frontend_verilog_yyset_lineno(0);
}
@@ -112,6 +116,9 @@ YOSYS_NAMESPACE_END
"`timescale"[ \t]+[^ \t\r\n/]+[ \t]*"/"[ \t]*[^ \t\r\n]* /* ignore timescale directive */
+"`celldefine"[^\n]* /* ignore `celldefine */
+"`endcelldefine"[^\n]* /* ignore `endcelldefine */
+
"`default_nettype"[ \t]+[^ \t\r\n/]+ {
char *p = yytext;
while (*p != 0 && *p != ' ' && *p != '\t') p++;
@@ -162,8 +169,9 @@ YOSYS_NAMESPACE_END
"always_ff" { SV_KEYWORD(TOK_ALWAYS); }
"always_latch" { SV_KEYWORD(TOK_ALWAYS); }
-"assert" { SV_KEYWORD(TOK_ASSERT); }
-"property" { SV_KEYWORD(TOK_PROPERTY); }
+"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
+"assume" { if (formal_mode) return TOK_ASSUME; return TOK_ID; }
+"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); }
"logic" { SV_KEYWORD(TOK_REG); }
"bit" { SV_KEYWORD(TOK_REG); }
@@ -177,12 +185,12 @@ YOSYS_NAMESPACE_END
"genvar" { return TOK_GENVAR; }
"real" { return TOK_REAL; }
-[0-9]+ {
+[0-9][0-9_]* {
frontend_verilog_yylval.string = new std::string(yytext);
return TOK_CONST;
}
-[0-9]*[ \t]*\'s?[bodh][ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
+[0-9]*[ \t]*\'s?[bodhBODH][ \t\r\n]*[0-9a-fA-FzxZX?_]+ {
frontend_verilog_yylval.string = new std::string(yytext);
return TOK_CONST;
}
@@ -240,7 +248,7 @@ and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 {
supply0 { return TOK_SUPPLY0; }
supply1 { return TOK_SUPPLY1; }
-"$"(display|time|stop|finish) {
+"$"(display|strobe|monitor|time|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) {
frontend_verilog_yylval.string = new std::string(yytext);
return TOK_ID;
}
@@ -254,8 +262,12 @@ supply1 { return TOK_SUPPLY1; }
}
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
- log("Warning: Found one of those horrible `(synopsys|synthesis) translate_off' comments.\n");
- log("It is strongly suggested to use `ifdef constructs instead!\n");
+ static bool printed_warning = false;
+ if (!printed_warning) {
+ log_warning("Found one of those horrible `(synopsys|synthesis) translate_off' comments.\n"
+ "Yosys does support them but it is recommended to use `ifdef constructs instead!\n");
+ printed_warning = true;
+ }
BEGIN(SYNOPSYS_TRANSLATE_OFF);
}
<SYNOPSYS_TRANSLATE_OFF>. /* ignore synopsys translate_off body */
@@ -266,13 +278,21 @@ supply1 { return TOK_SUPPLY1; }
BEGIN(SYNOPSYS_FLAGS);
}
<SYNOPSYS_FLAGS>full_case {
- log("Warning: Found one of those horrible `(synopsys|synthesis) full_case' comments.\n");
- log("It is strongly suggested to use verilog x-values and default branches instead!\n");
+ static bool printed_warning = false;
+ if (!printed_warning) {
+ log_warning("Found one of those horrible `(synopsys|synthesis) full_case' comments.\n"
+ "Yosys does support them but it is recommended to use verilog `full_case' attributes instead!\n");
+ printed_warning = true;
+ }
return TOK_SYNOPSYS_FULL_CASE;
}
<SYNOPSYS_FLAGS>parallel_case {
- log("Warning: Found one of those horrible `(synopsys|synthesis) parallel_case' comments.\n");
- log("It is strongly suggested to use verilog `parallel_case' attributes instead!\n");
+ static bool printed_warning = false;
+ if (!printed_warning) {
+ log_warning("Found one of those horrible `(synopsys|synthesis) parallel_case' comments.\n"
+ "Yosys does support them but it is recommended to use verilog `parallel_case' attributes instead!\n");
+ printed_warning = true;
+ }
return TOK_SYNOPSYS_PARALLEL_CASE;
}
<SYNOPSYS_FLAGS>. /* ignore everything else */
@@ -342,7 +362,10 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
[ \t\r\n] /* ignore whitespaces */
\\[\r\n] /* ignore continuation sequence */
"//"[^\r\n]* /* ignore one-line comments */
-"#"[$a-zA-Z_0-9\.]+ /* ignore simulation timings */
+
+"#"\ *[0-9][0-9_]* /* ignore simulation timings */
+"#"\ *[0-9][0-9_]*\.[0-9][0-9_]* /* ignore simulation timings */
+"#"\ *[$a-zA-Z_\.][$a-zA-Z_0-9\.]* /* ignore simulation timings */
. { return *yytext; }
diff --git a/frontends/verilog/parser.y b/frontends/verilog/verilog_parser.y
index a9f69a49c..d935cab37 100644
--- a/frontends/verilog/parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -57,7 +57,7 @@ namespace VERILOG_FRONTEND {
std::vector<char> case_type_stack;
bool do_not_require_port_stubs;
bool default_nettype_wire;
- bool sv_mode;
+ bool sv_mode, formal_mode;
std::istream *lexin;
}
YOSYS_NAMESPACE_END
@@ -111,7 +111,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
%token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL
%token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
-%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_PROPERTY
+%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME TOK_PROPERTY
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
@@ -139,10 +139,11 @@ static void free_attr(std::map<std::string, AstNode*> *al)
%%
input: {
+ ast_stack.clear();
ast_stack.push_back(current_ast);
} design {
ast_stack.pop_back();
- log_assert(SIZE(ast_stack) == 0);
+ log_assert(GetSize(ast_stack) == 0);
for (auto &it : default_attr_list)
delete it.second;
default_attr_list.clear();
@@ -240,7 +241,7 @@ module:
};
module_para_opt:
- '#' '(' module_para_list ')' | /* empty */;
+ '#' '(' { astbuf1 = nullptr; } module_para_list { if (astbuf1) delete astbuf1; } ')' | /* empty */;
module_para_list:
single_module_para |
@@ -249,11 +250,10 @@ module_para_list:
single_module_para:
TOK_PARAMETER {
+ if (astbuf1) delete astbuf1;
astbuf1 = new AstNode(AST_PARAMETER);
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
- } param_signed param_integer param_range single_param_decl {
- delete astbuf1;
- };
+ } param_signed param_integer param_range single_param_decl | single_param_decl;
module_args_opt:
'(' ')' | /* empty */ | '(' module_args optional_comma ')';
@@ -310,10 +310,17 @@ module_arg:
do_not_require_port_stubs = true;
};
+non_opt_delay:
+ '#' '(' expr ')' { delete $3; } |
+ '#' '(' expr ':' expr ':' expr ')' { delete $3; delete $5; delete $7; };
+
+delay:
+ non_opt_delay | /* empty */;
+
wire_type:
{
astbuf3 = new AstNode(AST_WIRE);
- } wire_type_token_list {
+ } wire_type_token_list delay {
$$ = astbuf3;
};
@@ -449,7 +456,7 @@ task_func_decl:
} opt_dpi_function_args ';' {
current_function_or_task = NULL;
} |
- attr TOK_TASK TOK_ID ';' {
+ attr TOK_TASK TOK_ID {
current_function_or_task = new AstNode(AST_TASK);
current_function_or_task->str = *$3;
append_attr(current_function_or_task, $1);
@@ -457,11 +464,11 @@ task_func_decl:
ast_stack.push_back(current_function_or_task);
current_function_or_task_port_id = 1;
delete $3;
- } task_func_body TOK_ENDTASK {
+ } task_func_args_opt ';' task_func_body TOK_ENDTASK {
current_function_or_task = NULL;
ast_stack.pop_back();
} |
- attr TOK_FUNCTION opt_signed range_or_signed_int TOK_ID ';' {
+ attr TOK_FUNCTION opt_signed range_or_signed_int TOK_ID {
current_function_or_task = new AstNode(AST_FUNCTION);
current_function_or_task->str = *$5;
append_attr(current_function_or_task, $1);
@@ -478,7 +485,7 @@ task_func_decl:
current_function_or_task->children.push_back(outreg);
current_function_or_task_port_id = 1;
delete $5;
- } task_func_body TOK_ENDFUNCTION {
+ } task_func_args_opt ';' task_func_body TOK_ENDFUNCTION {
current_function_or_task = NULL;
ast_stack.pop_back();
};
@@ -512,6 +519,45 @@ opt_signed:
$$ = false;
};
+task_func_args_opt:
+ '(' ')' | /* empty */ | '(' {
+ albuf = nullptr;
+ astbuf1 = nullptr;
+ astbuf2 = nullptr;
+ } task_func_args optional_comma {
+ delete astbuf1;
+ if (astbuf2 != NULL)
+ delete astbuf2;
+ free_attr(albuf);
+ } ')';
+
+task_func_args:
+ task_func_port | task_func_args ',' task_func_port;
+
+task_func_port:
+ attr wire_type range {
+ if (albuf) {
+ delete astbuf1;
+ if (astbuf2 != NULL)
+ delete astbuf2;
+ free_attr(albuf);
+ }
+ albuf = $1;
+ astbuf1 = $2;
+ astbuf2 = $3;
+ if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
+ if (astbuf2) {
+ frontend_verilog_yyerror("Syntax error.");
+ } else {
+ astbuf2 = new AstNode(AST_RANGE);
+ astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true));
+ astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true));
+ }
+ }
+ if (astbuf2 && astbuf2->children.size() != 2)
+ frontend_verilog_yyerror("Syntax error.");
+ } wire_name | wire_name;
+
task_func_body:
task_func_body behavioral_stmt |
/* empty */;
@@ -568,6 +614,8 @@ param_decl_list:
single_param_decl:
TOK_ID '=' expr {
+ if (astbuf1 == nullptr)
+ frontend_verilog_yyerror("syntax error");
AstNode *node = astbuf1->clone();
node->str = *$1;
delete node->children[0];
@@ -609,27 +657,39 @@ wire_decl:
}
if (astbuf2 && astbuf2->children.size() != 2)
frontend_verilog_yyerror("Syntax error.");
- } wire_name_list ';' {
+ } wire_name_list {
delete astbuf1;
if (astbuf2 != NULL)
delete astbuf2;
free_attr(albuf);
- } |
- attr TOK_SUPPLY0 TOK_ID ';' {
+ } ';' |
+ attr TOK_SUPPLY0 TOK_ID {
ast_stack.back()->children.push_back(new AstNode(AST_WIRE));
ast_stack.back()->children.back()->str = *$3;
append_attr(ast_stack.back()->children.back(), $1);
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(0, false, 1)));
ast_stack.back()->children.back()->children[0]->str = *$3;
delete $3;
- } |
- attr TOK_SUPPLY1 TOK_ID ';' {
+ } opt_supply_wires ';' |
+ attr TOK_SUPPLY1 TOK_ID {
ast_stack.back()->children.push_back(new AstNode(AST_WIRE));
ast_stack.back()->children.back()->str = *$3;
append_attr(ast_stack.back()->children.back(), $1);
ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(1, false, 1)));
ast_stack.back()->children.back()->children[0]->str = *$3;
delete $3;
+ } opt_supply_wires ';';
+
+opt_supply_wires:
+ /* empty */ |
+ opt_supply_wires ',' TOK_ID {
+ AstNode *wire_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-2)->clone();
+ AstNode *assign_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-1)->clone();
+ wire_node->str = *$3;
+ assign_node->children[0]->str = *$3;
+ ast_stack.back()->children.push_back(wire_node);
+ ast_stack.back()->children.push_back(assign_node);
+ delete $3;
};
wire_name_list:
@@ -689,7 +749,7 @@ wire_name:
};
assign_stmt:
- TOK_ASSIGN assign_expr_list ';';
+ TOK_ASSIGN delay assign_expr_list ';';
assign_expr_list:
assign_expr | assign_expr_list ',' assign_expr;
@@ -709,7 +769,7 @@ cell_stmt:
} cell_parameter_list_opt cell_list ';' {
delete astbuf1;
} |
- attr tok_prim_wrapper {
+ attr tok_prim_wrapper delay {
astbuf1 = new AstNode(AST_PRIMITIVE);
astbuf1->str = *$2;
append_attr(astbuf1, $1);
@@ -874,27 +934,34 @@ opt_label:
assert:
TOK_ASSERT '(' expr ')' ';' {
ast_stack.back()->children.push_back(new AstNode(AST_ASSERT, $3));
+ } |
+ TOK_ASSUME '(' expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $3));
};
assert_property:
TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
ast_stack.back()->children.push_back(new AstNode(AST_ASSERT, $4));
+ } |
+ TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
+ ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
};
simple_behavioral_stmt:
- lvalue '=' expr {
- AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $3);
+ lvalue '=' delay expr {
+ AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $4);
ast_stack.back()->children.push_back(node);
} |
- lvalue OP_LE expr {
- AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $3);
+ lvalue OP_LE delay expr {
+ AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $4);
ast_stack.back()->children.push_back(node);
};
// this production creates the obligatory if-else shift/reduce conflict
behavioral_stmt:
defattr | assert | wire_decl |
- simple_behavioral_stmt ';' |
+ non_opt_delay behavioral_stmt |
+ simple_behavioral_stmt ';' | ';' |
hierarchical_id attr {
AstNode *node = new AstNode(AST_TCALL);
node->str = *$1;
@@ -1008,10 +1075,6 @@ opt_synopsys_attr:
} |
/* empty */;
-behavioral_stmt_opt:
- behavioral_stmt |
- ';' ;
-
behavioral_stmt_list:
behavioral_stmt_list behavioral_stmt |
/* empty */;
@@ -1040,7 +1103,7 @@ case_item:
ast_stack.back()->children.push_back(block);
ast_stack.push_back(block);
case_type_stack.push_back(0);
- } behavioral_stmt_opt {
+ } behavioral_stmt {
case_type_stack.pop_back();
ast_stack.pop_back();
ast_stack.pop_back();
@@ -1211,7 +1274,7 @@ basic_expr:
if ($4->substr(0, 1) != "'")
frontend_verilog_yyerror("Syntax error.");
AstNode *bits = $2;
- AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back());
+ AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), true);
if (val == NULL)
log_error("Value conversion failed: `%s'\n", $4->c_str());
$$ = new AstNode(AST_TO_BITS, bits, val);
@@ -1222,7 +1285,7 @@ basic_expr:
frontend_verilog_yyerror("Syntax error.");
AstNode *bits = new AstNode(AST_IDENTIFIER);
bits->str = *$1;
- AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back());
+ AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), true);
if (val == NULL)
log_error("Value conversion failed: `%s'\n", $2->c_str());
$$ = new AstNode(AST_TO_BITS, bits, val);
@@ -1230,14 +1293,14 @@ basic_expr:
delete $2;
} |
TOK_CONST TOK_CONST {
- $$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back());
+ $$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), true);
if ($$ == NULL || (*$2)[0] != '\'')
log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str());
delete $1;
delete $2;
} |
TOK_CONST {
- $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back());
+ $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), true);
if ($$ == NULL)
log_error("Value conversion failed: `%s'\n", $1->c_str());
delete $1;
@@ -1278,10 +1341,15 @@ basic_expr:
'(' expr ')' {
$$ = $2;
} |
+ '(' expr ':' expr ':' expr ')' {
+ delete $2;
+ $$ = $4;
+ delete $6;
+ } |
'{' concat_list '}' {
$$ = $2;
} |
- '{' expr '{' expr '}' '}' {
+ '{' expr '{' concat_list '}' '}' {
$$ = new AstNode(AST_REPLICATE, $2, $4);
} |
'~' attr basic_expr %prec UNARY_OPS {