sv: fix some edge cases for unbased unsized literals
authorZachary Snow <zach@zachjs.com>
Wed, 3 Mar 2021 19:36:19 +0000 (14:36 -0500)
committerZachary Snow <zachary.j.snow@gmail.com>
Sat, 6 Mar 2021 20:20:34 +0000 (15:20 -0500)
- Fix explicit size cast of unbased unsized literals
- Fix unbased unsized literal bound directly to port
- Output `is_unsized` flag in `dumpAst`

frontends/ast/ast.cc
frontends/ast/simplify.cc
tests/verilog/unbased_unsized.sv [new file with mode: 0644]
tests/verilog/unbased_unsized.ys [new file with mode: 0644]

index 57552d86c620b5783669b5ebf4976f7a9ccff1bd..88e6aa1c9386cc75c1be052dcc24d597b3de7b35 100644 (file)
@@ -317,6 +317,8 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
                fprintf(f, " reg");
        if (is_signed)
                fprintf(f, " signed");
+       if (is_unsized)
+               fprintf(f, " unsized");
        if (basic_prep)
                fprintf(f, " basic_prep");
        if (lookahead)
index 5c4dd290f7b8640b110c98d00776da145fb84872..e7f897b3c8d556f93277b07c205d0ec5111e87dc 100644 (file)
@@ -915,6 +915,22 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                        }
        }
 
+       if (type == AST_ARGUMENT)
+       {
+               if (children.size() == 1 && children[0]->type == AST_CONSTANT)
+               {
+                       // HACK: For port bindings using unbased unsized literals, mark them
+                       // signed so they sign-extend. The hierarchy will still incorrectly
+                       // generate a warning complaining about resizing the expression.
+                       // This also doesn't handle the complex of something like a ternary
+                       // expression bound to a port, where the actual size of the port is
+                       // needed to resolve the expression correctly.
+                       AstNode *arg = children[0];
+                       if (arg->is_unsized)
+                               arg->is_signed = true;
+               }
+       }
+
        int backup_width_hint = width_hint;
        bool backup_sign_hint = sign_hint;
 
@@ -3773,7 +3789,11 @@ replace_fcall_later:;
                case AST_CAST_SIZE:
                        if (children.at(0)->type == AST_CONSTANT && children.at(1)->type == AST_CONSTANT) {
                                int width = children[0]->bitsAsConst().as_int();
-                               RTLIL::Const val = children[1]->bitsAsConst(width);
+                               RTLIL::Const val;
+                               if (children[1]->is_unsized)
+                                       val = children[1]->bitsAsUnsizedConst(width);
+                               else
+                                       val = children[1]->bitsAsConst(width);
                                newNode = mkconst_bits(val.bits, children[1]->is_signed);
                        }
                        break;
diff --git a/tests/verilog/unbased_unsized.sv b/tests/verilog/unbased_unsized.sv
new file mode 100644 (file)
index 0000000..1d0c5a7
--- /dev/null
@@ -0,0 +1,40 @@
+module pass_through(
+    input [63:0] inp,
+    output [63:0] out
+);
+    assign out = inp;
+endmodule
+
+module top;
+    logic [63:0]
+        o01, o02, o03, o04,
+        o05, o06, o07, o08,
+        o09, o10, o11, o12,
+        o13, o14, o15, o16;
+    assign o01 = '0;
+    assign o02 = '1;
+    assign o03 = 'x;
+    assign o04 = 'z;
+    assign o05 = 3'('0);
+    assign o06 = 3'('1);
+    assign o07 = 3'('x);
+    assign o08 = 3'('z);
+    pass_through pt09('0, o09);
+    pass_through pt10('1, o10);
+    pass_through pt11('x, o11);
+    pass_through pt12('z, o12);
+    always @* begin
+        assert (o01 === {64 {1'b0}});
+        assert (o02 === {64 {1'b1}});
+        assert (o03 === {64 {1'bx}});
+        assert (o04 === {64 {1'bz}});
+        assert (o05 === {61'b0, 3'b000});
+        assert (o06 === {61'b0, 3'b111});
+        assert (o07 === {61'b0, 3'bxxx});
+        assert (o08 === {61'b0, 3'bzzz});
+        assert (o09 === {64 {1'b0}});
+        assert (o10 === {64 {1'b1}});
+        assert (o11 === {64 {1'bx}});
+        assert (o12 === {64 {1'bz}});
+    end
+endmodule
diff --git a/tests/verilog/unbased_unsized.ys b/tests/verilog/unbased_unsized.ys
new file mode 100644 (file)
index 0000000..e1bc99c
--- /dev/null
@@ -0,0 +1,7 @@
+read_verilog -sv unbased_unsized.sv
+hierarchy
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all