diff options
author | Zachary Snow <zach@zachjs.com> | 2021-02-21 14:45:21 -0500 |
---|---|---|
committer | Zachary Snow <zach@zachjs.com> | 2021-02-21 15:44:43 -0500 |
commit | b6af90fe20bc92631061c48c328f3c6e4760e4df (patch) | |
tree | 9c8fb14f37ae5c4339fd550b7c8322e70c4cf940 /frontends | |
parent | 127484e675538fbaeca1f6e53ba264a1f02e9cf6 (diff) | |
download | yosys-b6af90fe20bc92631061c48c328f3c6e4760e4df.tar.gz yosys-b6af90fe20bc92631061c48c328f3c6e4760e4df.tar.bz2 yosys-b6af90fe20bc92631061c48c328f3c6e4760e4df.zip |
verilog: fix sizing of constant args for tasks/functions
- Simplify synthetic localparams for normal calls to update their width
- This step was inadvertently removed alongside `added_mod_children`
- Support redeclaration of constant function arguments
- `eval_const_function` never correctly handled this, but the issue
was not exposed in the existing tests until the recent change to
always attempt constant function evaluation when all-const args
are used
- Check asserts in const_arg_loop and const_func tests
- Add coverage for width mismatch error cases
Diffstat (limited to 'frontends')
-rw-r--r-- | frontends/ast/ast.h | 8 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 32 |
2 files changed, 30 insertions, 10 deletions
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index d8818df31..b793c6c2d 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -263,7 +263,13 @@ namespace AST bool detect_latch(const std::string &var); // additional functionality for evaluating constant functions - struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; }; + struct varinfo_t { + RTLIL::Const val; + int offset; + bool is_signed; + AstNode *arg = nullptr; + bool explicitly_sized; + }; bool has_const_only_constructs(); bool replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall, bool must_succeed); AstNode *eval_const_function(AstNode *fcall, bool must_succeed); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 402b7257b..df7c9282c 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -3376,6 +3376,8 @@ skip_dynamic_range_lvalue_expansion:; range->children.push_back(mkconst_int(0, true)); } } + // updates the sizing + while (wire->simplify(true, false, false, 1, -1, false, false)) { } continue; } AstNode *wire_id = new AstNode(AST_IDENTIFIER); @@ -4591,17 +4593,29 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed) log_file_error(stmt->filename, stmt->location.first_line, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n", stmt->str.c_str(), fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column); } - variables[stmt->str].val = RTLIL::Const(RTLIL::State::Sx, abs(stmt->range_left - stmt->range_right)+1); - variables[stmt->str].offset = min(stmt->range_left, stmt->range_right); - variables[stmt->str].is_signed = stmt->is_signed; + AstNode::varinfo_t &variable = variables[stmt->str]; + int width = abs(stmt->range_left - stmt->range_right) + 1; + // if this variable has already been declared as an input, check the + // sizes match if it already had an explicit size + if (variable.arg && variable.explicitly_sized && variable.val.size() != width) { + log_file_error(filename, location.first_line, "Incompatible re-declaration of constant function wire %s.\n", stmt->str.c_str()); + } + variable.val = RTLIL::Const(RTLIL::State::Sx, width); + variable.offset = min(stmt->range_left, stmt->range_right); + variable.is_signed = stmt->is_signed; + variable.explicitly_sized = stmt->children.size() && + stmt->children.back()->type == AST_RANGE; + // identify the argument corresponding to this wire, if applicable if (stmt->is_input && argidx < fcall->children.size()) { - int width = variables[stmt->str].val.bits.size(); - auto* arg_node = fcall->children.at(argidx++); - if (arg_node->type == AST_CONSTANT) { - variables[stmt->str].val = arg_node->bitsAsConst(width); + variable.arg = fcall->children.at(argidx++); + } + // load the constant arg's value into this variable + if (variable.arg) { + if (variable.arg->type == AST_CONSTANT) { + variable.val = variable.arg->bitsAsConst(width); } else { - log_assert(arg_node->type == AST_REALVALUE); - variables[stmt->str].val = arg_node->realAsConst(width); + log_assert(variable.arg->type == AST_REALVALUE); + variable.val = variable.arg->realAsConst(width); } } current_scope[stmt->str] = stmt; |