diff options
author | whitequark <whitequark@whitequark.org> | 2021-01-01 09:32:26 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-01 09:32:26 +0000 |
commit | bc2de4567c46c555c453061b7e24db695a7ae62b (patch) | |
tree | b324d9f5c9558411846741fac6c3049970f469f8 /frontends | |
parent | 1a80194cd30adea054da17ebecfcbd921b34aeb5 (diff) | |
parent | 2085d9a55d38f28551739d63bede29d93edaf578 (diff) | |
download | yosys-bc2de4567c46c555c453061b7e24db695a7ae62b.tar.gz yosys-bc2de4567c46c555c453061b7e24db695a7ae62b.tar.bz2 yosys-bc2de4567c46c555c453061b7e24db695a7ae62b.zip |
Merge pull request #2518 from zachjs/recursion
verilog: improved support for recursive functions
Diffstat (limited to 'frontends')
-rw-r--r-- | frontends/ast/ast.h | 2 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 34 |
2 files changed, 28 insertions, 8 deletions
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; } |