aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJannis Harder <me@jix.one>2022-05-31 15:56:36 +0200
committerGitHub <noreply@github.com>2022-05-31 15:56:36 +0200
commit01cb02c81df14762cce117a823af742ed044a5c4 (patch)
treee766145cefa1dc2acf65be28fc0f12e9d0c51e49
parenta79a228c2ba3259a1d8783f69990acd10e0efb5a (diff)
parenta650d9079fa4732a6d118f2764d5abc2522a6b37 (diff)
downloadyosys-01cb02c81df14762cce117a823af742ed044a5c4.tar.gz
yosys-01cb02c81df14762cce117a823af742ed044a5c4.tar.bz2
yosys-01cb02c81df14762cce117a823af742ed044a5c4.zip
Merge pull request #3348 from zachjs/func-tern-hint
verilog: fix width/sign detection for functions
-rw-r--r--CHANGELOG2
-rw-r--r--frontends/ast/genrtlil.cc12
-rw-r--r--tests/verilog/func_tern_hint.sv42
-rw-r--r--tests/verilog/func_tern_hint.ys4
4 files changed, 55 insertions, 5 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 4ee364a57..60e53aa6c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,6 +14,8 @@ Yosys 0.17 .. Yosys 0.17-dev
the remaining cases
- Fixed size and signedness computation for expressions containing array
querying functions
+ - Fixed size and signedness computation of functions used in ternary
+ expressions or case item expressions
Yosys 0.16 .. Yosys 0.17
--------------------------
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index a569c5ae2..d81c53dfb 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -1095,8 +1095,9 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (current_scope.count(str))
{
// This width detection is needed for function calls which are
- // unelaborated, which currently only applies to calls to recursive
- // functions reached by unevaluated ternary branches.
+ // unelaborated, which currently applies to calls to functions
+ // reached via unevaluated ternary branches or used in case or case
+ // item expressions.
const AstNode *func = current_scope.at(str);
if (func->type != AST_FUNCTION)
log_file_error(filename, location.first_line, "Function call to %s resolved to something that isn't a function!\n", RTLIL::unescape_id(str).c_str());
@@ -1107,8 +1108,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
break;
}
log_assert(wire && wire->type == AST_WIRE);
- sign_hint = wire->is_signed;
- width_hint = 1;
+ sign_hint &= wire->is_signed;
+ int result_width = 1;
if (!wire->children.empty())
{
log_assert(wire->children.size() == 1);
@@ -1121,10 +1122,11 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (left->type != AST_CONSTANT || right->type != AST_CONSTANT)
log_file_error(filename, location.first_line, "Function %s has non-constant width!",
RTLIL::unescape_id(str).c_str());
- width_hint = abs(int(left->asInt(true) - right->asInt(true)));
+ result_width = abs(int(left->asInt(true) - right->asInt(true)));
delete left;
delete right;
}
+ width_hint = max(width_hint, result_width);
break;
}
YS_FALLTHROUGH
diff --git a/tests/verilog/func_tern_hint.sv b/tests/verilog/func_tern_hint.sv
new file mode 100644
index 000000000..3c58c9913
--- /dev/null
+++ b/tests/verilog/func_tern_hint.sv
@@ -0,0 +1,42 @@
+module top;
+ function automatic [30:0] func;
+ input integer inp;
+ func = { // self-determined context
+ (
+ inp == 0
+ ? -1 // causes whole ternary to be 32 bits
+ : func(inp - 1) // 31 bits, unsigned
+ ) >> 2};
+ endfunction
+ function automatic signed [3:0] dunk;
+ input integer inp;
+ dunk = (
+ inp == 0
+ ? 4'hF
+ // shouldn't make the ternary signed
+ : dunk(inp - 1)
+ ) == -1;
+ endfunction
+ localparam A = func(0);
+ localparam B = func(1);
+ localparam C = func(2);
+ localparam D = func(3);
+ localparam X = dunk(0);
+ localparam Y = dunk(1);
+ initial begin
+ assert(A == 31'h3F_FFFFFF);
+ assert(B == 31'h0F_FFFFFF);
+ assert(C == 31'h03_FFFFFF);
+ assert(D == 31'h00_FFFFFF);
+ assert(X == 0);
+ assert(Y == 0);
+ end
+ initial begin
+ logic x;
+ case (1'b1)
+ dunk(0): x = 0;
+ default: x = 1;
+ endcase
+ assert(x);
+ end
+endmodule
diff --git a/tests/verilog/func_tern_hint.ys b/tests/verilog/func_tern_hint.ys
new file mode 100644
index 000000000..ab8a1e032
--- /dev/null
+++ b/tests/verilog/func_tern_hint.ys
@@ -0,0 +1,4 @@
+read_verilog -sv func_tern_hint.sv
+proc
+opt
+sat -verify -seq 1 -prove-asserts -show-all