diff options
author | whitequark <whitequark@whitequark.org> | 2021-02-21 20:56:04 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-21 20:56:04 +0000 |
commit | 01ccb80b708b45926b3690949479715ebf5e2853 (patch) | |
tree | aa2f7cf94cd7b1742568d05d744dc6e21b266306 /frontends/ast/genrtlil.cc | |
parent | 3fee43cde0ec424e52ea62f78722b061aaac280a (diff) | |
parent | 8de2e863af4233aca0a0ca0eef4477d216f7a227 (diff) | |
download | yosys-01ccb80b708b45926b3690949479715ebf5e2853.tar.gz yosys-01ccb80b708b45926b3690949479715ebf5e2853.tar.bz2 yosys-01ccb80b708b45926b3690949479715ebf5e2853.zip |
Merge pull request #2586 from zachjs/tern-recurse
verilog: support recursive functions using ternary expressions
Diffstat (limited to 'frontends/ast/genrtlil.cc')
-rw-r--r-- | frontends/ast/genrtlil.cc | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 24f5e1bef..713e34eb1 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -944,6 +944,41 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun } break; } + if (current_scope.count(str)) + { + // This width detection is needed for function calls which are + // unelaborated, which currently only applies to calls to recursive + // functions reached by unevaluated ternary branches. + const AstNode *func = current_scope.at(str); + if (func->type != AST_FUNCTION) + log_file_error(filename, location.first_line, "Function call to %s resolved to something that isn't a function!\n", RTLIL::unescape_id(str).c_str()); + const AstNode *wire = nullptr; + for (const AstNode *child : func->children) + if (child->str == func->str) { + wire = child; + break; + } + log_assert(wire && wire->type == AST_WIRE); + sign_hint = wire->is_signed; + width_hint = 1; + if (!wire->children.empty()) + { + log_assert(wire->children.size() == 1); + const AstNode *range = wire->children.at(0); + log_assert(range->type == AST_RANGE && range->children.size() == 2); + AstNode *left = range->children.at(0)->clone(); + AstNode *right = range->children.at(1)->clone(); + while (left->simplify(true, false, false, 1, -1, false, true)) { } + while (right->simplify(true, false, false, 1, -1, false, true)) { } + if (left->type != AST_CONSTANT || right->type != AST_CONSTANT) + log_file_error(filename, location.first_line, "Function %s has non-constant width!", + RTLIL::unescape_id(str).c_str()); + width_hint = abs(int(left->asInt(true) - right->asInt(true))); + delete left; + delete right; + } + break; + } YS_FALLTHROUGH // everything should have been handled above -> print error if not. |