Fix output C++ type error on change detect of I/O arrays (#5125) (#5131)

operand order reversed for AstCMethodHard "neq"
interface between C-style arrays and VlUnpacked
overloads added to VlUnpacked::neq(), VlUnpacked::assign()
VlUnpacked::operator=() added

Fixes  #5125
This commit is contained in:
Pawel Jewstafjew 2024-05-22 12:53:28 +01:00 committed by GitHub
parent d9078df650
commit 913679f261
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 122 additions and 2 deletions

View File

@ -147,6 +147,7 @@ Oleh Maksymenko
Patrick Stewart
Paul Swirhun
Paul Wright
Pawel Jewstafjew
Pawel Sagan
Pengcheng Xu
Peter Debacker

View File

@ -1321,7 +1321,11 @@ public:
// Similar to 'neq' above, *this = that used for change detection
void assign(const VlUnpacked<T_Value, T_Depth>& that) { *this = that; }
bool operator==(const VlUnpacked<T_Value, T_Depth>& that) const { return !neq(that); }
bool operator!=(const VlUnpacked<T_Value, T_Depth>& that) { return neq(that); }
bool operator!=(const VlUnpacked<T_Value, T_Depth>& that) const { return neq(that); }
// interface to C style arrays (used in ports), see issue #5125
bool neq(const T_Value that[T_Depth]) const { return neq(*this, that); }
void assign(const T_Value that[T_Depth]) { std::copy_n(that, T_Depth, m_storage); }
void operator=(const T_Value that[T_Depth]) { assign(that); }
// inside (set membership operator)
bool inside(const T_Value& value) const {
@ -1511,6 +1515,15 @@ private:
return false;
}
template <typename T_Val, std::size_t T_Dep>
static bool neq(const VlUnpacked<T_Val, T_Dep>& a, const T_Val b[T_Dep]) {
for (size_t i = 0; i < T_Dep; ++i) {
// Recursive 'neq', in case T_Val is also a VlUnpacked<_, _>
if (neq(a.m_storage[i], b[i])) return true;
}
return false;
}
template <typename T_Other> //
static bool neq(const T_Other& a, const T_Other& b) {
// Base case (T_Other is not VlUnpacked<_, _>), fall back on !=

View File

@ -167,7 +167,8 @@ class SenExprBuilder final {
case VEdgeType::ET_CHANGED:
case VEdgeType::ET_HYBRID: //
if (VN_IS(senp->dtypep()->skipRefp(), UnpackArrayDType)) {
AstCMethodHard* const resultp = new AstCMethodHard{flp, currp(), "neq", prevp()};
// operand order reversed to avoid calling neq() method on non-VlUnpacked type, see issue #5125
AstCMethodHard* const resultp = new AstCMethodHard{flp, prevp(), "neq", currp()};
resultp->dtypeSetBit();
return {resultp, true};
}

22
test_regress/t/t_type_match.pl Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(simulator => 1);
compile(
verilator_flags2 => ["-Wno-UNOPTFLAT"]
);
execute(
check_finished => 1,
);
ok(1);
1;

View File

@ -0,0 +1,83 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This module takes a single clock input, and should either
// $write("*-* All Finished *-*\n");
// $finish;
// on success, or $stop.
//
// issue #5125
// type used for __Vtrigprevexpr signal do not match type used for i/o port
//
// Generated C++ code should compile.
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Pawel Jewstafjew (Pawel.Jewstafjew@gmail.com).
// SPDX-License-Identifier: CC0-1.0
module t (clk);
input clk;
logic a;
logic d;
top i_top(.*);
integer cnt;
initial cnt=1;
always @ (posedge clk)
begin
cnt <= cnt + 1;
a <= cnt[0];
$display("%d %d %d", cnt, a, d);
if (d != a)
$stop;
if (cnt == 10) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module top (
input a,
output d
);
logic b;
logic c[1];
assign c[0] = b;
unit i_unit
(
.a (a),
.b (b),
.c (c),
.d (d)
);
endmodule
module unit
(
input a,
input c[1],
output logic b,
output logic d
);
// no_inline required to prevent optimising away the interesing part ...
/*verilator no_inline_module*/
always_comb
begin
b = a;
d = b && c[0];
end
endmodule