verilog: fix signedness when removing unreachable cases
authorJannis Harder <me@jix.one>
Tue, 24 May 2022 12:32:14 +0000 (14:32 +0200)
committerZachary Snow <zachary.j.snow@gmail.com>
Wed, 25 May 2022 03:03:31 +0000 (23:03 -0400)
CHANGELOG
frontends/ast/simplify.cc
tests/verilog/unreachable_case_sign.ys [new file with mode: 0644]

index 4004c534b8e1e75e330f17ee3d87f704a5fab854..ff7ce49a25ae6c9df6dc70d14b1a6cf7435661d3 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -5,6 +5,11 @@ List of major changes and improvements between releases
 Yosys 0.17 .. Yosys 0.17-dev
 --------------------------
 
+ * Verilog
+    - Fixed an issue where simplifying case statements by removing unreachable
+      cases could result in the wrong signedness being used for comparison with
+      the remaining cases
+
 Yosys 0.16 .. Yosys 0.17
 --------------------------
  * New commands and options
index bd3e09c4b9cc09633d3193bf38f348b38a93303e..4d7c4f5221429aa977a425ddf2fd9a43d8199e6a 100644 (file)
@@ -1531,6 +1531,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                detectSignWidth(width_hint, sign_hint);
                while (children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
                if (children[0]->type == AST_CONSTANT && children[0]->bits_only_01()) {
+                       children[0]->is_signed = sign_hint;
                        RTLIL::Const case_expr = children[0]->bitsAsConst(width_hint, sign_hint);
                        std::vector<AstNode*> new_children;
                        new_children.push_back(children[0]);
diff --git a/tests/verilog/unreachable_case_sign.ys b/tests/verilog/unreachable_case_sign.ys
new file mode 100644 (file)
index 0000000..25bc0c6
--- /dev/null
@@ -0,0 +1,33 @@
+logger -expect-no-warnings
+
+read_verilog -formal <<EOT
+module top(input clk);
+    reg good = 0;
+
+    always @(posedge clk) begin
+        case (4'sb1111) 15: good = 1; 4'b0000: ; endcase
+        assert (good);
+    end
+endmodule
+EOT
+
+prep -top top
+sim -n 3 -clock clk
+
+design -reset
+
+read_verilog -formal <<EOT
+module top(input clk);
+    reg good = 1;
+    reg signed [1:0] case_value = -1;
+
+    always @(posedge clk) begin
+        case (4'sb1111) 4'b0000: ; case_value: good = 0; endcase
+        assert (good);
+    end
+endmodule
+EOT
+
+prep -top top
+sim -n 3 -clock clk
+