Support assignment patterns as comparison operands (#7269)
* Support assignment patterns as EQ/NEQ comparison operands * Apply 'make format' * update the .out file * add both-sides case --------- Co-authored-by: github action <action@example.com>
This commit is contained in:
parent
ef5281ab73
commit
316fb02c60
|
|
@ -7545,8 +7545,22 @@ class WidthVisitor final : public VNVisitor {
|
|||
UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!");
|
||||
assertAtExpr(nodep);
|
||||
if (m_vup->prelim()) {
|
||||
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||
// Assignment patterns cannot self-determine their type.
|
||||
// Iterate the non-pattern operand first so its dtype is available,
|
||||
// then propagate that dtype to the pattern operand (analogous to
|
||||
// how assignments pass LHS dtype to RHS patterns).
|
||||
const bool lhsIsPat = VN_IS(nodep->lhsp(), Pattern);
|
||||
const bool rhsIsPat = VN_IS(nodep->rhsp(), Pattern);
|
||||
if (lhsIsPat && !rhsIsPat) {
|
||||
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||
userIterateAndNext(nodep->lhsp(), WidthVP{nodep->rhsp()->dtypep(), PRELIM}.p());
|
||||
} else if (rhsIsPat && !lhsIsPat) {
|
||||
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||
userIterateAndNext(nodep->rhsp(), WidthVP{nodep->lhsp()->dtypep(), PRELIM}.p());
|
||||
} else {
|
||||
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||
userIterateAndNext(nodep->rhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||
}
|
||||
|
||||
const bool isAggrLhs = isAggregateType(nodep->lhsp());
|
||||
const bool isAggrRhs = isAggregateType(nodep->rhsp());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of either the GNU Lesser General Public License Version 3
|
||||
# or the Perl Artistic License Version 2.0.
|
||||
# SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
// DESCRIPTION: Verilator: Test assignment patterns as comparison operands
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 PlanV GmbH
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t;
|
||||
|
||||
// Fixed-size array comparison
|
||||
int arr4[4];
|
||||
typedef int arr4_t[4];
|
||||
|
||||
// Queue comparison
|
||||
int q[$];
|
||||
int sub[$];
|
||||
|
||||
// Struct comparison
|
||||
typedef struct packed {
|
||||
logic [7:0] a;
|
||||
logic [7:0] b;
|
||||
} pair_t;
|
||||
|
||||
pair_t p1;
|
||||
|
||||
// Nested: array of structs
|
||||
pair_t parr[2];
|
||||
|
||||
// Different element types
|
||||
logic [31:0] wide_arr[3];
|
||||
byte byte_arr[2];
|
||||
|
||||
initial begin
|
||||
// -------------------------------------------------------
|
||||
// 1. Fixed-size array: EQ with assignment pattern
|
||||
// -------------------------------------------------------
|
||||
arr4 = '{10, 20, 30, 40};
|
||||
if (arr4 == '{10, 20, 30, 40}) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: arr4 == pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
// 2. Fixed-size array: NEQ with assignment pattern
|
||||
if (arr4 != '{10, 20, 30, 99}) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: arr4 != pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
// 3. Pattern on LHS of comparison
|
||||
if ('{10, 20, 30, 40} == arr4) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: pattern == arr4 (LHS)");
|
||||
$stop;
|
||||
end
|
||||
|
||||
// 4. Pattern on LHS of NEQ
|
||||
if ('{10, 20, 30, 99} != arr4) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: pattern != arr4 (LHS NEQ)");
|
||||
$stop;
|
||||
end
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 5. Queue: EQ with assignment pattern
|
||||
// -------------------------------------------------------
|
||||
q = '{10, 20, 30, 40, 50};
|
||||
sub = q[1:3];
|
||||
if (sub == '{20, 30, 40}) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: queue slice == pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
// 6. Queue: NEQ with assignment pattern
|
||||
if (sub != '{20, 30, 99}) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: queue slice != pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 7. Struct: EQ with assignment pattern
|
||||
// -------------------------------------------------------
|
||||
p1 = '{a: 8'hAA, b: 8'h55};
|
||||
if (p1 == '{a: 8'hAA, b: 8'h55}) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: struct == pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
// 8. Struct: NEQ with assignment pattern
|
||||
if (p1 != '{a: 8'hAA, b: 8'hFF}) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: struct != pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 9. Array of structs: EQ with nested pattern
|
||||
// -------------------------------------------------------
|
||||
parr[0] = '{a: 8'h01, b: 8'h02};
|
||||
parr[1] = '{a: 8'h03, b: 8'h04};
|
||||
if (parr == '{'{a: 8'h01, b: 8'h02}, '{a: 8'h03, b: 8'h04}}) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: array of structs == nested pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 10. Different element widths
|
||||
// -------------------------------------------------------
|
||||
wide_arr = '{32'hDEAD_BEEF, 32'hCAFE_BABE, 32'h1234_5678};
|
||||
if (wide_arr == '{32'hDEAD_BEEF, 32'hCAFE_BABE, 32'h1234_5678}) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: wide array == pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
byte_arr = '{8'hAB, 8'hCD};
|
||||
if (byte_arr == '{8'hAB, 8'hCD}) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: byte array == pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 11. Negative case: pattern that should not match
|
||||
// -------------------------------------------------------
|
||||
if (arr4 == '{99, 99, 99, 99}) begin
|
||||
$display("FAIL: arr4 should not match all-99 pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
// -------------------------------------------------------
|
||||
// 12. Both sides are typed assignment patterns
|
||||
// -------------------------------------------------------
|
||||
if (arr4_t'{10, 20, 30, 40} == arr4_t'{10, 20, 30, 40}) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: typed pattern == typed pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
if (arr4_t'{10, 20, 30, 40} != arr4_t'{10, 20, 30, 99}) begin
|
||||
// expected
|
||||
end else begin
|
||||
$display("FAIL: typed pattern != typed pattern");
|
||||
$stop;
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -1,22 +1,5 @@
|
|||
%Error-UNSUPPORTED: t/t_stream_unpack_lhs.v:112:34: Unsupported/Illegal: Assignment pattern member not underneath a supported construct: NEQ
|
||||
: ... note: In instance 't'
|
||||
112 | if (unpacked_siz_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
| ^~
|
||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
||||
%Error-UNSUPPORTED: t/t_stream_unpack_lhs.v:113:34: Unsupported/Illegal: Assignment pattern member not underneath a supported construct: NEQ
|
||||
: ... note: In instance 't'
|
||||
113 | if (unpacked_asc_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_stream_unpack_lhs.v:114:34: Unsupported/Illegal: Assignment pattern member not underneath a supported construct: NEQ
|
||||
: ... note: In instance 't'
|
||||
114 | if (unpacked_des_dout != '{8'h76, 8'h54, 8'h32, 8'h10}) $stop;
|
||||
| ^~
|
||||
%Error-UNSUPPORTED: t/t_stream_unpack_lhs.v:116:32: Unsupported/Illegal: Assignment pattern member not underneath a supported construct: NEQ
|
||||
: ... note: In instance 't'
|
||||
116 | if (packed_siz_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
| ^~
|
||||
%Error: Internal Error: t/t_stream_unpack_lhs.v:116:32: ../V3Width.cpp:#: Node has no type
|
||||
: ... note: In instance 't'
|
||||
116 | if (packed_siz_dout != '{8'h01, 8'h23, 8'h45, 8'h67}) $stop;
|
||||
| ^~
|
||||
... This fatal error may be caused by the earlier error(s); resolve those first.
|
||||
%Error: Internal Error: t/t_stream_unpack_lhs.v:58:85: ../V3Const.cpp:#: sWidth >= dWidth should have caused an error earlier
|
||||
: ... note: In instance 't'
|
||||
58 | {>>{concat5_dout4, concat5_dout3, concat5_dout2, concat5_dout1, concat5_dout0}} = concat_din;
|
||||
| ^
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
|
|
|
|||
Loading…
Reference in New Issue