sv: fix size cast internal expression extension
authorZachary Snow <zach@zachjs.com>
Thu, 6 Jan 2022 06:33:08 +0000 (23:33 -0700)
committerZachary Snow <zachary.j.snow@gmail.com>
Sat, 8 Jan 2022 04:21:02 +0000 (21:21 -0700)
CHANGELOG
frontends/ast/genrtlil.cc
tests/verilog/size_cast.sv [new file with mode: 0644]
tests/verilog/size_cast.ys [new file with mode: 0644]

index 9402f9bbb1ef60e271ad0d60d3f9e343b4ce820e..cd6c1ed2602d1f731c67b48819e26dfab873c920 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -18,6 +18,8 @@ Yosys 0.11 .. Yosys 0.12
       expressions and case item expressions
     - Fixed static size casts inadvertently limiting the result width of binary
       operations
+    - Fixed static size casts ignoring expression signedness
+    - Fixed static size casts not extending unbased unsized literals
 
  * New commands and options
     - Added "-genlib" option to "abc" pass
index 2788a850f8f9231b42e10d3b4c4edabd9e3d4dfa..4c25287add25425182ccbafb7dbdb68878d72a78 100644 (file)
@@ -1531,13 +1531,20 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
        // changing the size of signal can be done directly using RTLIL::SigSpec
        case AST_CAST_SIZE: {
                        RTLIL::SigSpec size = children[0]->genRTLIL();
-                       RTLIL::SigSpec sig = children[1]->genRTLIL();
                        if (!size.is_fully_const())
                                log_file_error(filename, location.first_line, "Static cast with non constant expression!\n");
                        int width = size.as_int();
                        if (width <= 0)
                                log_file_error(filename, location.first_line, "Static cast with zero or negative size!\n");
-                       sig.extend_u0(width, sign_hint);
+                       // determine the *signedness* of the expression
+                       int sub_width_hint = -1;
+                       bool sub_sign_hint = true;
+                       children[1]->detectSignWidth(sub_width_hint, sub_sign_hint);
+                       // generate the signal given the *cast's* size and the
+                       // *expression's* signedness
+                       RTLIL::SigSpec sig = children[1]->genWidthRTLIL(width, sub_sign_hint);
+                       // context may effect this node's signedness, but not that of the
+                       // casted expression
                        is_signed = sign_hint;
                        return sig;
                }
diff --git a/tests/verilog/size_cast.sv b/tests/verilog/size_cast.sv
new file mode 100644 (file)
index 0000000..1636f8d
--- /dev/null
@@ -0,0 +1,140 @@
+module top;
+    logic L1b0 = 0;
+    logic L1b1 = 1;
+
+    logic signed L1sb0 = 0;
+    logic signed L1sb1 = 1;
+
+    logic [1:0] L2b00 = 0;
+    logic [1:0] L2b01 = 1;
+    logic [1:0] L2b10 = 2;
+    logic [1:0] L2b11 = 3;
+
+    logic signed [1:0] L2sb00 = 0;
+    logic signed [1:0] L2sb01 = 1;
+    logic signed [1:0] L2sb10 = 2;
+    logic signed [1:0] L2sb11 = 3;
+
+    logic y = 1;
+
+    always @* begin
+
+        assert (1'(L1b0  ) == 1'b0);
+        assert (1'(L1b1  ) == 1'b1);
+        assert (1'(L1sb0 ) == 1'b0);
+        assert (1'(L1sb1 ) == 1'b1);
+        assert (1'(L2b00 ) == 1'b0);
+        assert (1'(L2b01 ) == 1'b1);
+        assert (1'(L2b10 ) == 1'b0);
+        assert (1'(L2b11 ) == 1'b1);
+        assert (1'(L2sb00) == 1'b0);
+        assert (1'(L2sb01) == 1'b1);
+        assert (1'(L2sb10) == 1'b0);
+        assert (1'(L2sb11) == 1'b1);
+
+        assert (2'(L1b0  ) == 2'b00);
+        assert (2'(L1b1  ) == 2'b01);
+        assert (2'(L1sb0 ) == 2'b00);
+        assert (2'(L1sb1 ) == 2'b11);
+        assert (2'(L2b00 ) == 2'b00);
+        assert (2'(L2b01 ) == 2'b01);
+        assert (2'(L2b10 ) == 2'b10);
+        assert (2'(L2b11 ) == 2'b11);
+        assert (2'(L2sb00) == 2'b00);
+        assert (2'(L2sb01) == 2'b01);
+        assert (2'(L2sb10) == 2'b10);
+        assert (2'(L2sb11) == 2'b11);
+
+        assert (3'(L1b0  ) == 3'b000);
+        assert (3'(L1b1  ) == 3'b001);
+        assert (3'(L1sb0 ) == 3'b000);
+        assert (3'(L1sb1 ) == 3'b111);
+        assert (3'(L2b00 ) == 3'b000);
+        assert (3'(L2b01 ) == 3'b001);
+        assert (3'(L2b10 ) == 3'b010);
+        assert (3'(L2b11 ) == 3'b011);
+        assert (3'(L2sb00) == 3'b000);
+        assert (3'(L2sb01) == 3'b001);
+        assert (3'(L2sb10) == 3'b110);
+        assert (3'(L2sb11) == 3'b111);
+
+        assert (3'(L1b0   | '1) == 3'b111);
+        assert (3'(L1b1   | '1) == 3'b111);
+        assert (3'(L1sb0  | '1) == 3'b111);
+        assert (3'(L1sb1  | '1) == 3'b111);
+        assert (3'(L2b00  | '1) == 3'b111);
+        assert (3'(L2b01  | '1) == 3'b111);
+        assert (3'(L2b10  | '1) == 3'b111);
+        assert (3'(L2b11  | '1) == 3'b111);
+        assert (3'(L2sb00 | '1) == 3'b111);
+        assert (3'(L2sb01 | '1) == 3'b111);
+        assert (3'(L2sb10 | '1) == 3'b111);
+        assert (3'(L2sb11 | '1) == 3'b111);
+
+        assert (3'(L1b0   | '0) == 3'b000);
+        assert (3'(L1b1   | '0) == 3'b001);
+        assert (3'(L1sb0  | '0) == 3'b000);
+        assert (3'(L1sb1  | '0) == 3'b001);
+        assert (3'(L2b00  | '0) == 3'b000);
+        assert (3'(L2b01  | '0) == 3'b001);
+        assert (3'(L2b10  | '0) == 3'b010);
+        assert (3'(L2b11  | '0) == 3'b011);
+        assert (3'(L2sb00 | '0) == 3'b000);
+        assert (3'(L2sb01 | '0) == 3'b001);
+        assert (3'(L2sb10 | '0) == 3'b010);
+        assert (3'(L2sb11 | '0) == 3'b011);
+
+        assert (3'(y ? L1b0   : '1) == 3'b000);
+        assert (3'(y ? L1b1   : '1) == 3'b001);
+        assert (3'(y ? L1sb0  : '1) == 3'b000);
+        assert (3'(y ? L1sb1  : '1) == 3'b001);
+        assert (3'(y ? L2b00  : '1) == 3'b000);
+        assert (3'(y ? L2b01  : '1) == 3'b001);
+        assert (3'(y ? L2b10  : '1) == 3'b010);
+        assert (3'(y ? L2b11  : '1) == 3'b011);
+        assert (3'(y ? L2sb00 : '1) == 3'b000);
+        assert (3'(y ? L2sb01 : '1) == 3'b001);
+        assert (3'(y ? L2sb10 : '1) == 3'b010);
+        assert (3'(y ? L2sb11 : '1) == 3'b011);
+
+        assert (3'(y ? L1b0   : '0) == 3'b000);
+        assert (3'(y ? L1b1   : '0) == 3'b001);
+        assert (3'(y ? L1sb0  : '0) == 3'b000);
+        assert (3'(y ? L1sb1  : '0) == 3'b001);
+        assert (3'(y ? L2b00  : '0) == 3'b000);
+        assert (3'(y ? L2b01  : '0) == 3'b001);
+        assert (3'(y ? L2b10  : '0) == 3'b010);
+        assert (3'(y ? L2b11  : '0) == 3'b011);
+        assert (3'(y ? L2sb00 : '0) == 3'b000);
+        assert (3'(y ? L2sb01 : '0) == 3'b001);
+        assert (3'(y ? L2sb10 : '0) == 3'b010);
+        assert (3'(y ? L2sb11 : '0) == 3'b011);
+
+        assert (3'(y ? L1b0   : 1'sb0) == 3'b000);
+        assert (3'(y ? L1b1   : 1'sb0) == 3'b001);
+        assert (3'(y ? L1sb0  : 1'sb0) == 3'b000);
+        assert (3'(y ? L1sb1  : 1'sb0) == 3'b111);
+        assert (3'(y ? L2b00  : 1'sb0) == 3'b000);
+        assert (3'(y ? L2b01  : 1'sb0) == 3'b001);
+        assert (3'(y ? L2b10  : 1'sb0) == 3'b010);
+        assert (3'(y ? L2b11  : 1'sb0) == 3'b011);
+        assert (3'(y ? L2sb00 : 1'sb0) == 3'b000);
+        assert (3'(y ? L2sb01 : 1'sb0) == 3'b001);
+        assert (3'(y ? L2sb10 : 1'sb0) == 3'b110);
+        assert (3'(y ? L2sb11 : 1'sb0) == 3'b111);
+
+        assert (3'(y ? L1b0   : 1'sb1) == 3'b000);
+        assert (3'(y ? L1b1   : 1'sb1) == 3'b001);
+        assert (3'(y ? L1sb0  : 1'sb1) == 3'b000);
+        assert (3'(y ? L1sb1  : 1'sb1) == 3'b111);
+        assert (3'(y ? L2b00  : 1'sb1) == 3'b000);
+        assert (3'(y ? L2b01  : 1'sb1) == 3'b001);
+        assert (3'(y ? L2b10  : 1'sb1) == 3'b010);
+        assert (3'(y ? L2b11  : 1'sb1) == 3'b011);
+        assert (3'(y ? L2sb00 : 1'sb1) == 3'b000);
+        assert (3'(y ? L2sb01 : 1'sb1) == 3'b001);
+        assert (3'(y ? L2sb10 : 1'sb1) == 3'b110);
+        assert (3'(y ? L2sb11 : 1'sb1) == 3'b111);
+
+    end
+endmodule
diff --git a/tests/verilog/size_cast.ys b/tests/verilog/size_cast.ys
new file mode 100644 (file)
index 0000000..6890cd2
--- /dev/null
@@ -0,0 +1,5 @@
+read_verilog -sv size_cast.sv
+proc
+opt -full
+select -module top
+sat -verify -prove-asserts -show-all