From bfb88f3d9473b1bb99ab3ecdb7dc77e9a0df3303 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Sun, 11 Feb 2024 13:28:14 -0500 Subject: [PATCH] verilog: indirect AST_CONCAT and AST_TO_UNSIGNED port connections - AST_CONCAT and AST_TO_UNSIGNED are always unsigned, but may generate RTLIL that exclusively reference a signed wire. - AST_CONCAT may also contain a memory write. --- CHANGELOG | 6 ++++ frontends/ast/genrtlil.cc | 8 ++--- frontends/ast/simplify.cc | 6 ++++ tests/simple/memwr_port_connection.sv | 10 +++--- tests/verilog/signed_concat.v | 45 +++++++++++++++++++++++++++ tests/verilog/signed_concat.ys | 7 +++++ 6 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 tests/verilog/signed_concat.v create mode 100644 tests/verilog/signed_concat.ys diff --git a/CHANGELOG b/CHANGELOG index f42eaca27e1..d2adc742b56 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,12 @@ List of major changes and improvements between releases Yosys 0.40 .. Yosys 0.41-dev -------------------------- + * Verilog + - Fixed an issue that prevented using `{}` or `$unsigned()` for + certain signed expressions in port connections + - Fixed an issue that prevented writing to a memory word via a concatenation + in an output port connection + Yosys 0.39 .. Yosys 0.40 -------------------------- * New commands and options diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index bc7f1ddd1d6..d90eeaf3ac6 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -2124,11 +2124,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (sig.is_wire()) { // if the resulting SigSpec is a wire, its // signedness should match that of the AstNode - if (arg->type == AST_IDENTIFIER && arg->id2ast && arg->id2ast->is_signed && !arg->is_signed) - // fully-sliced signed wire will be resolved - // once the module becomes available - log_assert(attributes.count(ID::reprocess_after)); - else + // unless this instantiation depends on module + // information that isn't available yet + if (!attributes.count(ID::reprocess_after)) log_assert(arg->is_signed == sig.as_wire()->is_signed); } else if (arg->is_signed) { // non-trivial signed nodes are indirected through diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 3d8478ef160..380a1bff493 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1292,6 +1292,12 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin else if (contains_unbased_unsized(value)) // unbased unsized literals extend to width of the context lookup_suggested = true; + else if (value->type == AST_TO_UNSIGNED) + // inner expression may be signed by default + lookup_suggested = true; + else if (value->type == AST_CONCAT && value->children.size() == 1) + // concat of a single expression is equivalent to $unsigned + lookup_suggested = true; } } diff --git a/tests/simple/memwr_port_connection.sv b/tests/simple/memwr_port_connection.sv index 5bf414e081c..bc60d7e52a9 100644 --- a/tests/simple/memwr_port_connection.sv +++ b/tests/simple/memwr_port_connection.sv @@ -5,9 +5,11 @@ module producer( endmodule module top( - output logic [3:0] out + output logic [3:0] out0, out1 ); - logic [3:0] v[0:0]; - producer p(v[0]); - assign out = v[0]; + logic [3:0] v[1:0]; + producer p0(v[0]); + producer p1({v[1]}); + assign out0 = v[0]; + assign out1 = v[1]; endmodule diff --git a/tests/verilog/signed_concat.v b/tests/verilog/signed_concat.v new file mode 100644 index 00000000000..ca5a5e02f32 --- /dev/null +++ b/tests/verilog/signed_concat.v @@ -0,0 +1,45 @@ +`define OUTPUTS(mode) \ + o``mode``0, \ + o``mode``1, \ + o``mode``2, \ + o``mode``3, \ + o``mode``4 + +module gate( + input [1:0] iu, + input signed [1:0] is, + output [2:0] `OUTPUTS(u), + output signed [2:0] `OUTPUTS(s) +); +`define INSTANCES(mode) \ + mod m``mode``0({i``mode}, {o``mode``0}); \ + mod m``mode``1($unsigned(i``mode), o``mode``1); \ + mod m``mode``2({i``mode[1:0]}, o``mode``2); \ + mod m``mode``3({$signed(i``mode)}, o``mode``3); \ + mod m``mode``4($unsigned({i``mode}), o``mode``4); +`INSTANCES(u) +`INSTANCES(s) +`undef INSTANCES +endmodule + +module gold( + input [1:0] iu, is, + output [2:0] `OUTPUTS(u), `OUTPUTS(s) +); +`define INSTANCES(mode) \ + assign o``mode``0 = i``mode; \ + assign o``mode``1 = i``mode; \ + assign o``mode``2 = i``mode; \ + assign o``mode``3 = i``mode; \ + assign o``mode``4 = i``mode; +`INSTANCES(u) +`INSTANCES(s) +`undef INSTANCES +endmodule + +module mod( + input [2:0] inp, + output [2:0] out +); + assign out = inp; +endmodule diff --git a/tests/verilog/signed_concat.ys b/tests/verilog/signed_concat.ys new file mode 100644 index 00000000000..44ede82d623 --- /dev/null +++ b/tests/verilog/signed_concat.ys @@ -0,0 +1,7 @@ +read_verilog signed_concat.v +hierarchy +proc +flatten gate +equiv_make gold gate equiv +equiv_simple +equiv_status -assert