Fix constants bound to redeclared function args
authorZachary Snow <zach@zachjs.com>
Sat, 26 Dec 2020 15:39:57 +0000 (08:39 -0700)
committerZachary Snow <zach@zachjs.com>
Sat, 26 Dec 2020 15:48:01 +0000 (08:48 -0700)
The changes in #2476 ensured that function inputs like `input x;`
retained their single-bit size when instantiated with a constant
argument and turned into a localparam. That change did not handle the
possibility for an input to be redeclared later on with an explicit
width, such as `integer x;`.

frontends/ast/simplify.cc
tests/various/const_arg_loop.v

index 5fa4ac83b2eb29b2640850b3c4b2ed4366c49f55..c6d63f247127d33f0407dd6e60e69dc755263d2c 100644 (file)
@@ -3344,11 +3344,22 @@ skip_dynamic_range_lvalue_expansion:;
                                                wire->children.insert(wire->children.begin(), arg->clone());
                                                // args without a range implicitly have width 1
                                                if (wire->children.back()->type != AST_RANGE) {
-                                                       AstNode* range = new AstNode();
-                                                       range->type = AST_RANGE;
-                                                       wire->children.push_back(range);
-                                                       range->children.push_back(mkconst_int(0, true));
-                                                       range->children.push_back(mkconst_int(0, true));
+                                                       // check if this wire is redeclared with an explicit size
+                                                       bool uses_explicit_size = false;
+                                                       for (const AstNode *other_child : decl->children)
+                                                               if (other_child->type == AST_WIRE && child->str == other_child->str
+                                                                               && !other_child->children.empty()
+                                                                               && other_child->children.back()->type == AST_RANGE) {
+                                                                       uses_explicit_size = true;
+                                                                       break;
+                                                               }
+                                                       if (!uses_explicit_size) {
+                                                               AstNode* range = new AstNode();
+                                                               range->type = AST_RANGE;
+                                                               wire->children.push_back(range);
+                                                               range->children.push_back(mkconst_int(0, true));
+                                                               range->children.push_back(mkconst_int(0, true));
+                                                       }
                                                }
                                                continue;
                                        }
index ed15aa13529b570c0845507556d050f0b88bb2a0..358fb439ae66ba1501d8e8f09366f877f8438bea 100644 (file)
@@ -50,6 +50,12 @@ module top;
                operation4 = {a, b};
        endfunction
 
+       function automatic integer operation5;
+               input x;
+               integer x;
+               operation5 = x;
+       endfunction
+
        wire [31:0] a;
        assign a = 2;
 
@@ -70,6 +76,9 @@ module top;
        wire [16:0] x4;
        assign x4 = operation4(a[15:0], 0);
 
+       wire [31:0] x5;
+       assign x5 = operation5(64);
+
 // `define VERIFY
 `ifdef VERIFY
     assert property (a == 2);
@@ -79,5 +88,6 @@ module top;
     assert property (x2 == 4);
     assert property (x3 == 16);
     assert property (x4 == a << 1);
+    assert property (x5 == 64);
 `endif
 endmodule