aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJannis Harder <me@jix.one>2023-04-20 12:12:50 +0200
committerJannis Harder <me@jix.one>2023-04-20 12:12:50 +0200
commit985f4926b77aef98a2639624a44e155b2233c3ad (patch)
treea0a072144adec6c43e4f283c321d2583b6e8baf5
parent7efc50367ed8f582001a5a293a9cd51f788f6a13 (diff)
downloadyosys-985f4926b77aef98a2639624a44e155b2233c3ad.tar.gz
yosys-985f4926b77aef98a2639624a44e155b2233c3ad.tar.bz2
yosys-985f4926b77aef98a2639624a44e155b2233c3ad.zip
verilog: Fix const eval of unbased unsized constants
When the verilog frontend perfomed constant evaluation of unbased unsized constants in a context-determined expression it did not properly extend them by repeating the bit value. This only affected constant evaluation and not constants that made it through unchanged to RTLIL. The latter case was already covered by tests and working before. This fixes the const-eval issue by checking the `is_unsized` flag in bitsAsConst and extending the value accordingly. The newly added test also tests the already working non-const-eval case to highlight that both cases should behave the same.
-rw-r--r--frontends/ast/ast.cc2
-rw-r--r--tests/verilog/unbased_unsized_shift.sv28
-rw-r--r--tests/verilog/unbased_unsized_shift.ys7
3 files changed, 36 insertions, 1 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 5a2ade04a..91001c70d 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -847,7 +847,7 @@ RTLIL::Const AstNode::bitsAsConst(int width, bool is_signed)
bits.resize(width);
if (width >= 0 && width > int(bits.size())) {
RTLIL::State extbit = RTLIL::State::S0;
- if (is_signed && !bits.empty())
+ if ((is_signed || is_unsized) && !bits.empty())
extbit = bits.back();
while (width > int(bits.size()))
bits.push_back(extbit);
diff --git a/tests/verilog/unbased_unsized_shift.sv b/tests/verilog/unbased_unsized_shift.sv
new file mode 100644
index 000000000..475e9a75d
--- /dev/null
+++ b/tests/verilog/unbased_unsized_shift.sv
@@ -0,0 +1,28 @@
+module pass_through(
+ input [63:0] inp,
+ output [63:0] out
+);
+ assign out = inp;
+endmodule
+
+module top;
+ logic [63:0] s0c, s1c, sxc, s0d, s1d, sxd, d;
+
+ pass_through pt(8, d);
+
+ assign s0c = '0 << 8;
+ assign s1c = '1 << 8;
+ assign sxc = 'x << 8;
+ assign s0d = '0 << d;
+ assign s1d = '1 << d;
+ assign sxd = 'x << d;
+
+ always @* begin
+ assert (s0c === 64'h0000_0000_0000_0000);
+ assert (s1c === 64'hFFFF_FFFF_FFFF_FF00);
+ assert (sxc === 64'hxxxx_xxxx_xxxx_xx00);
+ assert (s0d === 64'h0000_0000_0000_0000);
+ assert (s1d === 64'hFFFF_FFFF_FFFF_FF00);
+ assert (sxd === 64'hxxxx_xxxx_xxxx_xx00);
+ end
+endmodule
diff --git a/tests/verilog/unbased_unsized_shift.ys b/tests/verilog/unbased_unsized_shift.ys
new file mode 100644
index 000000000..c36049600
--- /dev/null
+++ b/tests/verilog/unbased_unsized_shift.ys
@@ -0,0 +1,7 @@
+read_verilog -sv unbased_unsized_shift.sv
+hierarchy
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all