verilog: fix size and signedness of array querying functions

genrtlil.cc and simplify.cc had inconsistent and slightly broken
handling of signedness for array querying functions. These functions are
defined to return a signed result. Simplify always produced an unsigned
and genrtlil always a signed 32-bit result ignoring the context.

Includes tests for the the relvant edge cases for context dependent
conversions.
This commit is contained in:
Jannis Harder 2022-05-20 21:46:39 +02:00 committed by Zachary Snow
parent ce24208a8b
commit 4bfaaea0d5
4 changed files with 56 additions and 3 deletions

View File

@ -12,6 +12,8 @@ Yosys 0.17 .. Yosys 0.17-dev
- 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
- Fixed size and signedness computation for expressions containing array
querying functions
Yosys 0.16 .. Yosys 0.17
--------------------------

View File

@ -1089,8 +1089,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
break;
}
if (str == "\\$size" || str == "\\$bits" || str == "\\$high" || str == "\\$low" || str == "\\$left" || str == "\\$right") {
width_hint = 32;
sign_hint = true;
width_hint = max(width_hint, 32);
break;
}
if (current_scope.count(str))

View File

@ -3450,7 +3450,7 @@ skip_dynamic_range_lvalue_expansion:;
else {
result = width * mem_depth;
}
newNode = mkconst_int(result, false);
newNode = mkconst_int(result, true);
goto apply_newNode;
}

View File

@ -0,0 +1,52 @@
logger -expect-no-warnings
read_verilog -formal <<EOT
module top(input clk);
reg [-1:-1] x;
reg good = 0;
reg signed [31:0] zero = 0;
always @(posedge clk) begin
case ($left(x) + zero) 36'shfffffffff: good = 1; 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 [-1:-1] x;
reg good = 0;
always @(posedge clk) begin
case ($left(x)) 36'sh0ffffffff: good = 1; (32'h0 + $left(good)): ; 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 [-1:-1] x;
reg good = 1;
always @(posedge clk) begin
case (36'sh100000000 + $left(x)) -1: good = 0; endcase
assert (good);
end
endmodule
EOT
prep -top top
sim -n 3 -clock clk