aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZachary Snow <zach@zachjs.com>2022-01-05 23:33:08 -0700
committerZachary Snow <zachary.j.snow@gmail.com>2022-01-07 21:21:02 -0700
commit828e85068f8dd52a508e4cbb84deea0e621aa038 (patch)
tree76b0563d045c07a894f3baa1454d256b0e895c6e
parent59a71503448401d2476cf0872808e0a99c3a4d81 (diff)
downloadyosys-828e85068f8dd52a508e4cbb84deea0e621aa038.tar.gz
yosys-828e85068f8dd52a508e4cbb84deea0e621aa038.tar.bz2
yosys-828e85068f8dd52a508e4cbb84deea0e621aa038.zip
sv: fix size cast internal expression extension
-rw-r--r--CHANGELOG2
-rw-r--r--frontends/ast/genrtlil.cc11
-rw-r--r--tests/verilog/size_cast.sv140
-rw-r--r--tests/verilog/size_cast.ys5
4 files changed, 156 insertions, 2 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 9402f9bbb..cd6c1ed26 100644
--- 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
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index 2788a850f..4c25287ad 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -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
index 000000000..1636f8d70
--- /dev/null
+++ b/tests/verilog/size_cast.sv
@@ -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
index 000000000..6890cd2d5
--- /dev/null
+++ b/tests/verilog/size_cast.ys
@@ -0,0 +1,5 @@
+read_verilog -sv size_cast.sv
+proc
+opt -full
+select -module top
+sat -verify -prove-asserts -show-all