Add IEEE 4-state type lint checks (#3645 partial) (#6895)

This commit is contained in:
Jose Drowne 2026-01-18 11:00:25 -05:00 committed by GitHub
parent 50b6954cfc
commit 3a080ef543
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 143 additions and 3 deletions

View File

@ -234,7 +234,7 @@ class AstNodeUOrStructDType VL_NOT_FINAL : public AstNodeDType {
string m_name; // Name from upper typedef, if any
const int m_uniqueNum;
bool m_packed;
bool m_isFourstate = false; // V3Width computes
bool m_isFourstate = false; // V3Width computes; true if any member is 4-state
bool m_constrainedRand = false; // True if struct has constraint expression
protected:

View File

@ -1871,9 +1871,11 @@ class LinkDotFindVisitor final : public VNVisitor {
nextp = argp->nextp();
AstVar* argrefp = nullptr;
if (AstParseRef* const parserefp = VN_CAST(argp, ParseRef)) {
// We use an int type, this might get changed in V3Width when types resolve
// IEEE 1800-2023 12.7.3: foreach loop variable type shall be int (2-state)
// This might get changed in V3Width when types resolve (e.g., for assoc
// arrays)
argrefp = new AstVar{parserefp->fileline(), VVarType::BLOCKTEMP,
parserefp->name(), argp->findSigned32DType()};
parserefp->name(), argp->findIntDType()};
argrefp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
parserefp->replaceWith(argrefp);
VL_DO_DANGLING2(parserefp->deleteTree(), parserefp, argp);

View File

@ -5761,6 +5761,34 @@ class WidthVisitor final : public VNVisitor {
}
}
// IEEE 1800-2023 7.6: For unpacked arrays to be assignment compatible,
// the element types shall be equivalent (IEEE 1800-2023 6.22.2).
// Check specifically for 2-state vs 4-state mismatch for unpacked array
// to unpacked array assignments, as this is a common IEEE compliance issue.
// Note: Streaming operators and string literals have implicit conversion rules.
if (nodep->rhsp()->dtypep()) { // May be null on earlier errors
const AstNodeDType* const lhsDtp = lhsDTypep->skipRefp();
const AstNodeDType* const rhsDtp = nodep->rhsp()->dtypep()->skipRefp();
// Only check unpacked array to unpacked array assignments
const bool lhsIsUnpackArray
= VN_IS(lhsDtp, UnpackArrayDType) || VN_IS(lhsDtp, DynArrayDType)
|| VN_IS(lhsDtp, QueueDType) || VN_IS(lhsDtp, AssocArrayDType);
const bool rhsIsUnpackArray
= VN_IS(rhsDtp, UnpackArrayDType) || VN_IS(rhsDtp, DynArrayDType)
|| VN_IS(rhsDtp, QueueDType) || VN_IS(rhsDtp, AssocArrayDType);
if (lhsIsUnpackArray && rhsIsUnpackArray) {
if (lhsDtp->isFourstate() != rhsDtp->isFourstate()) {
nodep->v3error(
"Assignment between 2-state and 4-state types requires "
"equivalent element types (IEEE 1800-2023 6.22.2, 7.6)\n"
<< nodep->warnMore() << "... LHS type: " << lhsDtp->prettyDTypeNameQ()
<< (lhsDtp->isFourstate() ? " (4-state)" : " (2-state)") << "\n"
<< nodep->warnMore() << "... RHS type: " << rhsDtp->prettyDTypeNameQ()
<< (rhsDtp->isFourstate() ? " (4-state)" : " (2-state)"));
}
}
}
iterateCheckAssign(nodep, "Assign RHS", nodep->rhsp(), FINAL, lhsDTypep);
// UINFOTREE(1, nodep, "", "AssignOut");
}

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2026 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
import vltest_bootstrap
test.scenarios('simulator')
test.compile()
test.execute()
test.passes()

View File

@ -0,0 +1,41 @@
// DESCRIPTION: Test for IEEE 1800-2023 6.22.2 - valid array assignments with matching state types
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2026 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t;
// 2-state arrays - assignment should work
bit [7:0] arr_2state_a [3:0];
bit [7:0] arr_2state_b [3:0];
// 4-state arrays - assignment should work
logic [7:0] arr_4state_a [3:0];
logic [7:0] arr_4state_b [3:0];
initial begin
// Initialize
arr_2state_a[0] = 8'h10;
arr_2state_a[1] = 8'h20;
arr_2state_a[2] = 8'h30;
arr_2state_a[3] = 8'h40;
arr_4state_a[0] = 8'hA0;
arr_4state_a[1] = 8'hB0;
arr_4state_a[2] = 8'hC0;
arr_4state_a[3] = 8'hD0;
// Valid assignments: same state types
arr_2state_b = arr_2state_a; // 2-state to 2-state: OK
arr_4state_b = arr_4state_a; // 4-state to 4-state: OK
// Verify
if (arr_2state_b[0] !== 8'h10) $stop;
if (arr_2state_b[3] !== 8'h40) $stop;
if (arr_4state_b[0] !== 8'hA0) $stop;
if (arr_4state_b[3] !== 8'hD0) $stop;
$write("*-* All Coverage *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,8 @@
%Error: t/t_fourstate_assign_bad.v:23:18: Assignment between 2-state and 4-state types requires equivalent element types (IEEE 1800-2023 6.22.2, 7.6)
: ... note: In instance 't'
: ... LHS type: 'bit[7:0]$[3:0]' (2-state)
: ... RHS type: 'logic[7:0]$[3:0]' (4-state)
23 | arr_2state = arr_4state;
| ^
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2026 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
import vltest_bootstrap
test.scenarios('linter')
test.lint(fails=True, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,27 @@
// DESCRIPTION: Test for IEEE 1800-2023 6.22.2 - 4-state to 2-state type equivalence
// This should produce a type error because bit and logic are not equivalent types
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2026 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t;
// IEEE 6.22.2: Packed arrays are equivalent if they contain the same number
// of total bits, are either all 2-state or all 4-state, and are either all
// signed or all unsigned.
// 2-state array
bit [7:0] arr_2state [3:0];
// 4-state array (should not be assignment compatible for unpacked arrays)
logic [7:0] arr_4state [3:0];
initial begin
// Per IEEE 7.6: For unpacked arrays to be assignment compatible,
// the element types shall be equivalent.
// bit[7:0] and logic[7:0] are NOT equivalent (one is 2-state, one is 4-state)
arr_2state = arr_4state;
$write("*-* All Coverage *-*\n");
$stop;
end
endmodule