Allow blocks with declarations within constant functions
authorZachary Snow <zach@zachjs.com>
Sat, 25 Jul 2020 16:16:12 +0000 (10:16 -0600)
committerZachary Snow <zach@zachjs.com>
Sat, 25 Jul 2020 16:16:12 +0000 (10:16 -0600)
frontends/ast/simplify.cc
tests/various/const_func_block_var.v [new file with mode: 0644]
tests/various/const_func_block_var.ys [new file with mode: 0644]

index 00f8c8df67cd336814993436369df50110aea2de..94ba95e5bf2e4445a0aca0fb61922a2fccda93cf 100644 (file)
@@ -4340,27 +4340,9 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
        size_t argidx = 0;
        for (auto child : children)
        {
-               if (child->type == AST_WIRE)
-               {
-                       while (child->simplify(true, false, false, 1, -1, false, true)) { }
-                       if (!child->range_valid)
-                               log_file_error(child->filename, child->location.first_line, "Can't determine size of variable %s\n%s:%d.%d-%d.%d: ... called from here.\n",
-                                               child->str.c_str(), fcall->filename.c_str(), fcall->location.first_line, fcall->location.first_column, fcall->location.last_line, fcall->location.last_column);
-                       variables[child->str].val = RTLIL::Const(RTLIL::State::Sx, abs(child->range_left - child->range_right)+1);
-                       variables[child->str].offset = min(child->range_left, child->range_right);
-                       variables[child->str].is_signed = child->is_signed;
-                       if (child->is_input && argidx < fcall->children.size())
-                               variables[child->str].val = fcall->children.at(argidx++)->bitsAsConst(variables[child->str].val.bits.size());
-                       backup_scope[child->str] = current_scope[child->str];
-                       current_scope[child->str] = child;
-                       continue;
-               }
-
                block->children.push_back(child->clone());
        }
 
-       log_assert(variables.count(str) != 0);
-
        while (!block->children.empty())
        {
                AstNode *stmt = block->children.front();
@@ -4372,6 +4354,27 @@ AstNode *AstNode::eval_const_function(AstNode *fcall)
                stmt->dumpAst(NULL, "stmt> ");
 #endif
 
+               if (stmt->type == AST_WIRE)
+               {
+                       while (stmt->simplify(true, false, false, 1, -1, false, true)) { }
+                       if (!stmt->range_valid)
+                               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;
+                       if (stmt->is_input && argidx < fcall->children.size())
+                               variables[stmt->str].val = fcall->children.at(argidx++)->bitsAsConst(variables[stmt->str].val.bits.size());
+                       if (!backup_scope.count(stmt->str))
+                               backup_scope[stmt->str] = current_scope[stmt->str];
+                       current_scope[stmt->str] = stmt;
+
+                       block->children.erase(block->children.begin());
+                       continue;
+               }
+
+               log_assert(variables.count(str) != 0);
+
                if (stmt->type == AST_ASSIGN_EQ)
                {
                        if (stmt->children.at(0)->type == AST_IDENTIFIER && stmt->children.at(0)->children.size() != 0 &&
diff --git a/tests/various/const_func_block_var.v b/tests/various/const_func_block_var.v
new file mode 100644 (file)
index 0000000..98e83aa
--- /dev/null
@@ -0,0 +1,23 @@
+module top(out);
+       function integer operation;
+               input integer num;
+               begin
+                       operation = 0;
+                       begin : op_i
+                               integer i;
+                               for (i = 0; i < 2; i = i + 1)
+                               begin : op_j
+                                       integer j;
+                                       for (j = i; j < i * 2; j = j + 1)
+                                               num = num + 1;
+                               end
+                               num = num * 2;
+                       end
+                       operation = num;
+               end
+       endfunction
+
+       localparam res = operation(4);
+       output wire [31:0] out;
+       assign out = res;
+endmodule
diff --git a/tests/various/const_func_block_var.ys b/tests/various/const_func_block_var.ys
new file mode 100644 (file)
index 0000000..7c2e85c
--- /dev/null
@@ -0,0 +1 @@
+read_verilog const_func_block_var.v