diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | frontends/ast/ast.h | 2 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 34 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 10 | ||||
-rw-r--r-- | tests/various/fib.v | 65 | ||||
-rw-r--r-- | tests/various/fib.ys | 6 | ||||
-rw-r--r-- | tests/various/func_port_implied_dir.sv | 23 | ||||
-rw-r--r-- | tests/various/func_port_implied_dir.ys | 6 |
8 files changed, 141 insertions, 11 deletions
@@ -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 |