aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--frontends/ast/ast.h2
-rw-r--r--frontends/ast/simplify.cc34
-rw-r--r--frontends/verilog/verilog_parser.y10
-rw-r--r--tests/various/fib.v65
-rw-r--r--tests/various/fib.ys6
-rw-r--r--tests/various/func_port_implied_dir.sv23
-rw-r--r--tests/various/func_port_implied_dir.ys6
8 files changed, 141 insertions, 11 deletions
diff --git a/Makefile b/Makefile
index cd9e77448..fd7816898 100644
--- a/Makefile
+++ b/Makefile
@@ -126,7 +126,7 @@ LDFLAGS += -rdynamic
LDLIBS += -lrt
endif
-YOSYS_VER := 0.9+3814
+YOSYS_VER := 0.9+3819
GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
OBJS = kernel/version_$(GIT_REV).o
@@ -514,8 +514,8 @@ endif
ifeq ($(ENABLE_GHDL),1)
GHDL_PREFIX ?= $(PREFIX)
-GHDL_INCLUDE_DIR ?= $(GHDL_DIR)/include
-GHDL_LIB_DIR ?= $(GHDL_DIR)/lib
+GHDL_INCLUDE_DIR ?= $(GHDL_PREFIX)/include
+GHDL_LIB_DIR ?= $(GHDL_PREFIX)/lib
CXXFLAGS += -I$(GHDL_INCLUDE_DIR) -DYOSYS_ENABLE_GHDL
LDLIBS += $(GHDL_LIB_DIR)/libghdl.a $(file <$(GHDL_LIB_DIR)/libghdl.link)
endif
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 1b8ed22ca..907392166 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -250,6 +250,7 @@ namespace AST
// simplify() creates a simpler AST by unrolling for-loops, expanding generate blocks, etc.
// it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL()
bool simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, int width_hint, bool sign_hint, bool in_param);
+ void replace_result_wire_name_in_function(const std::string &from, const std::string &to);
AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init);
void expand_genblock(std::string index_var, std::string prefix, std::map<std::string, std::string> &name_map, bool original_scope = true);
void replace_ids(const std::string &prefix, const std::map<std::string, std::string> &rules);
@@ -264,6 +265,7 @@ namespace AST
// additional functionality for evaluating constant functions
struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; };
bool has_const_only_constructs(bool &recommend_const_eval);
+ bool has_const_only_constructs(std::set<std::string>& visited, bool &recommend_const_eval);
void replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall);
AstNode *eval_const_function(AstNode *fcall);
bool is_simple_const_expr();
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 17b4d4cdc..d4242f1e7 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -3175,6 +3175,8 @@ skip_dynamic_range_lvalue_expansion:;
if (all_args_const) {
AstNode *func_workspace = current_scope[str]->clone();
+ func_workspace->str = NEW_ID.str();
+ func_workspace->replace_result_wire_name_in_function(str, func_workspace->str);
newNode = func_workspace->eval_const_function(this);
delete func_workspace;
goto apply_newNode;
@@ -3714,12 +3716,12 @@ apply_newNode:
return did_something;
}
-static void replace_result_wire_name_in_function(AstNode *node, std::string &from, std::string &to)
+void AstNode::replace_result_wire_name_in_function(const std::string &from, const std::string &to)
{
- for (auto &it : node->children)
- replace_result_wire_name_in_function(it, from, to);
- if (node->str == from)
- node->str = to;
+ for (AstNode *child : children)
+ child->replace_result_wire_name_in_function(from, to);
+ if (str == from && type != AST_FCALL && type != AST_TCALL)
+ str = to;
}
// replace a readmem[bh] TCALL ast node with a block of memory assignments
@@ -3912,7 +3914,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma
name_map[child->str] = new_name;
if (child->type == AST_FUNCTION)
- replace_result_wire_name_in_function(child, child->str, new_name);
+ child->replace_result_wire_name_in_function(child->str, new_name);
else
child->str = new_name;
current_scope[new_name] = child;
@@ -4492,15 +4494,31 @@ bool AstNode::detect_latch(const std::string &var)
bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
{
+ std::set<std::string> visited;
+ return has_const_only_constructs(visited, recommend_const_eval);
+}
+
+bool AstNode::has_const_only_constructs(std::set<std::string>& visited, bool &recommend_const_eval)
+{
+ if (type == AST_FUNCTION || type == AST_TASK)
+ {
+ if (visited.count(str))
+ {
+ recommend_const_eval = true;
+ return false;
+ }
+ visited.insert(str);
+ }
+
if (type == AST_FOR)
recommend_const_eval = true;
if (type == AST_WHILE || type == AST_REPEAT)
return true;
if (type == AST_FCALL && current_scope.count(str))
- if (current_scope[str]->has_const_only_constructs(recommend_const_eval))
+ if (current_scope[str]->has_const_only_constructs(visited, recommend_const_eval))
return true;
for (auto child : children)
- if (child->AstNode::has_const_only_constructs(recommend_const_eval))
+ if (child->AstNode::has_const_only_constructs(visited, recommend_const_eval))
return true;
return false;
}
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 678ce6c87..6c4b06d7f 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -884,7 +884,11 @@ task_func_args:
task_func_port:
attr wire_type range {
+ bool prev_was_input = true;
+ bool prev_was_output = false;
if (albuf) {
+ prev_was_input = astbuf1->is_input;
+ prev_was_output = astbuf1->is_output;
delete astbuf1;
if (astbuf2 != NULL)
delete astbuf2;
@@ -893,6 +897,12 @@ task_func_port:
albuf = $1;
astbuf1 = $2;
astbuf2 = checkRange(astbuf1, $3);
+ if (!astbuf1->is_input && !astbuf1->is_output) {
+ if (!sv_mode)
+ frontend_verilog_yyerror("task/function argument direction missing");
+ astbuf1->is_input = prev_was_input;
+ astbuf1->is_output = prev_was_output;
+ }
} wire_name |
{
if (!astbuf1) {
diff --git a/tests/various/fib.v b/tests/various/fib.v
new file mode 100644
index 000000000..986749626
--- /dev/null
+++ b/tests/various/fib.v
@@ -0,0 +1,65 @@
+module gate(
+ off, fib0, fib1, fib2, fib3, fib4, fib5, fib6, fib7, fib8, fib9
+);
+ input wire signed [31:0] off;
+
+ function automatic integer fib(
+ input integer k
+ );
+ if (k == 0)
+ fib = 0;
+ else if (k == 1)
+ fib = 1;
+ else
+ fib = fib(k - 1) + fib(k - 2);
+ endfunction
+
+ function automatic integer fib_wrap(
+ input integer k,
+ output integer o
+ );
+ o = off + fib(k);
+ endfunction
+
+ output integer fib0;
+ output integer fib1;
+ output integer fib2;
+ output integer fib3;
+ output integer fib4;
+ output integer fib5;
+ output integer fib6;
+ output integer fib7;
+ output integer fib8;
+ output integer fib9;
+
+ initial begin : blk
+ integer unused;
+ unused = fib_wrap(0, fib0);
+ unused = fib_wrap(1, fib1);
+ unused = fib_wrap(2, fib2);
+ unused = fib_wrap(3, fib3);
+ unused = fib_wrap(4, fib4);
+ unused = fib_wrap(5, fib5);
+ unused = fib_wrap(6, fib6);
+ unused = fib_wrap(7, fib7);
+ unused = fib_wrap(8, fib8);
+ unused = fib_wrap(9, fib9);
+ end
+endmodule
+
+module gold(
+ off, fib0, fib1, fib2, fib3, fib4, fib5, fib6, fib7, fib8, fib9
+);
+ input wire signed [31:0] off;
+
+ output integer fib0 = off + 0;
+ output integer fib1 = off + 1;
+ output integer fib2 = off + 1;
+ output integer fib3 = off + 2;
+ output integer fib4 = off + 3;
+ output integer fib5 = off + 5;
+ output integer fib6 = off + 8;
+ output integer fib7 = off + 13;
+ output integer fib8 = off + 21;
+ output integer fib9 = off + 34;
+endmodule
diff --git a/tests/various/fib.ys b/tests/various/fib.ys
new file mode 100644
index 000000000..946e0738a
--- /dev/null
+++ b/tests/various/fib.ys
@@ -0,0 +1,6 @@
+read_verilog fib.v
+hierarchy
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert
diff --git a/tests/various/func_port_implied_dir.sv b/tests/various/func_port_implied_dir.sv
new file mode 100644
index 000000000..0424f1b46
--- /dev/null
+++ b/tests/various/func_port_implied_dir.sv
@@ -0,0 +1,23 @@
+module gate(w, x, y, z);
+ function automatic integer bar(
+ integer a
+ );
+ bar = 2 ** a;
+ endfunction
+ output integer w = bar(4);
+
+ function automatic integer foo(
+ input integer a, /* implicitly input */ integer b,
+ output integer c, /* implicitly output */ integer d
+ );
+ c = 42;
+ d = 51;
+ foo = a + b + 1;
+ endfunction
+ output integer x, y, z;
+ initial x = foo(1, 2, y, z);
+endmodule
+
+module gold(w, x, y, z);
+ output integer w = 16, x = 4, y = 42, z = 51;
+endmodule
diff --git a/tests/various/func_port_implied_dir.ys b/tests/various/func_port_implied_dir.ys
new file mode 100644
index 000000000..b5c22a05b
--- /dev/null
+++ b/tests/various/func_port_implied_dir.ys
@@ -0,0 +1,6 @@
+read_verilog -sv func_port_implied_dir.sv
+hierarchy
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert