forked from github/verilator
Fix lint for non-integral types in packed structs.
This commit is contained in:
parent
260d58e47e
commit
15d0ec317d
1
Changes
1
Changes
@ -84,6 +84,7 @@ Verilator 5.006 2023-01-22
|
||||
* Fix foreach unnamedblk duplicate error (#3885). [Ilya Barkov]
|
||||
* Fix elaboration of member selected classes (#3890). [Ilya Barkov]
|
||||
* Fix mismatched widths in DFG (#3872). [Geza Lore, Yike Zhou]
|
||||
* Fix lint for non-integral types in packed structs.
|
||||
|
||||
|
||||
Verilator 5.004 2022-12-14
|
||||
|
@ -566,7 +566,8 @@ public:
|
||||
}
|
||||
bool isIntNumeric() const { // Enum increment supported
|
||||
return (m_e == BIT || m_e == BYTE || m_e == INT || m_e == INTEGER || m_e == LOGIC
|
||||
|| m_e == LONGINT || m_e == SHORTINT || m_e == UINT32 || m_e == UINT64);
|
||||
|| m_e == LONGINT || m_e == SHORTINT || m_e == UINT32 || m_e == UINT64
|
||||
|| m_e == TIME);
|
||||
}
|
||||
bool isBitLogic() const { // Bit/logic vector types; can form a packed array
|
||||
return (m_e == LOGIC || m_e == BIT);
|
||||
|
@ -60,6 +60,8 @@ public:
|
||||
/// are compound when methods calls operate on object, or when
|
||||
/// under another compound-requiring object e.g. class
|
||||
virtual bool isCompound() const = 0;
|
||||
// Integral or packed, allowed inside an unpacked union/struct
|
||||
virtual bool isIntegralOrPacked() const { return !isCompound(); }
|
||||
// (Slow) recurse down to find basic data type
|
||||
virtual AstBasicDType* basicp() const = 0;
|
||||
// recurses over typedefs/const/enum to next non-typeref type
|
||||
@ -473,6 +475,7 @@ public:
|
||||
VNumRange declRange() const { return isRanged() ? VNumRange{left(), right()} : VNumRange{}; }
|
||||
void cvtRangeConst(); // Convert to smaller representation
|
||||
bool isCompound() const override { return isString(); }
|
||||
bool isIntegralOrPacked() const override { return keyword().isIntNumeric(); }
|
||||
};
|
||||
class AstBracketArrayDType final : public AstNodeDType {
|
||||
// Associative/Queue/Normal array data type, ie "[dtype_or_expr]"
|
||||
@ -1319,6 +1322,7 @@ public:
|
||||
std::vector<AstUnpackArrayDType*> unpackDimensions();
|
||||
void isCompound(bool flag) { m_isCompound = flag; }
|
||||
bool isCompound() const override VL_MT_SAFE { return m_isCompound; }
|
||||
bool isIntegralOrPacked() const override { return false; }
|
||||
};
|
||||
|
||||
// === AstNodeUOrStructDType ===
|
||||
|
@ -675,7 +675,7 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool AstNodeDType::isFourstate() const { return basicp()->isFourstate(); }
|
||||
bool AstNodeDType::isFourstate() const { return basicp() && basicp()->isFourstate(); }
|
||||
|
||||
class AstNodeDType::CTypeRecursed final {
|
||||
public:
|
||||
|
@ -2512,9 +2512,9 @@ private:
|
||||
}
|
||||
void visit(AstNodeUOrStructDType* nodep) override {
|
||||
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
|
||||
UINFO(5, " NODECLASS " << nodep << endl);
|
||||
UINFO(5, " NODEUORS " << nodep << endl);
|
||||
// if (debug() >= 9) nodep->dumpTree("- class-in: ");
|
||||
if (!nodep->packed() && v3Global.opt.structsPacked()) { nodep->packed(true); }
|
||||
if (!nodep->packed() && v3Global.opt.structsPacked()) nodep->packed(true);
|
||||
userIterateChildren(nodep, nullptr); // First size all members
|
||||
nodep->repairMemberCache();
|
||||
nodep->dtypep(nodep);
|
||||
@ -2523,16 +2523,23 @@ private:
|
||||
if (VN_IS(nodep, UnionDType) || nodep->packed()) {
|
||||
int lsb = 0;
|
||||
int width = 0;
|
||||
// MSB is first, so go backwards
|
||||
// Report errors on first member first
|
||||
AstMemberDType* itemp;
|
||||
for (itemp = nodep->membersp(); itemp; itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||
AstNodeDType* const dtp = itemp->subDTypep()->skipRefp();
|
||||
if (nodep->packed()
|
||||
&& !dtp->isIntegralOrPacked()
|
||||
// Historically lax:
|
||||
&& !v3Global.opt.structsPacked())
|
||||
itemp->v3error("Unpacked data type "
|
||||
<< dtp->prettyDTypeNameQ()
|
||||
<< " in packed struct/union (IEEE 1800-2017 7.2.1)");
|
||||
}
|
||||
// MSB is first, so loop backwards
|
||||
for (itemp = nodep->membersp(); itemp && itemp->nextp();
|
||||
itemp = VN_AS(itemp->nextp(), MemberDType)) {}
|
||||
for (AstMemberDType* backip; itemp; itemp = backip) {
|
||||
if (itemp->skipRefp()->isCompound())
|
||||
itemp->v3error(
|
||||
"Unpacked data type in packed struct/union (IEEE 1800-2017 7.2.1)");
|
||||
for (; itemp; itemp = VN_CAST(itemp->backp(), MemberDType)) {
|
||||
if (itemp->isFourstate()) nodep->isFourstate(true);
|
||||
backip = VN_CAST(itemp->backp(), MemberDType);
|
||||
itemp->lsb(lsb);
|
||||
if (VN_IS(nodep, UnionDType)) {
|
||||
width = std::max(width, itemp->width());
|
||||
|
@ -1,4 +1,4 @@
|
||||
%Error: t/t_flag_structs_packed.v:14:19: Unpacked data type in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
%Error: t/t_flag_structs_packed.v:14:19: Unpacked data type 'STRUCTDTYPE 'x.notpacked_t'' in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
: ... In instance x
|
||||
14 | notpacked_t b;
|
||||
| ^
|
||||
|
41
test_regress/t/t_struct_contents_bad.out
Normal file
41
test_regress/t/t_struct_contents_bad.out
Normal file
@ -0,0 +1,41 @@
|
||||
%Error: t/t_struct_contents_bad.v:20:19: Unpacked data type 'real' in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
: ... In instance t
|
||||
20 | real r;
|
||||
| ^
|
||||
%Error: t/t_struct_contents_bad.v:22:19: Unpacked data type 'real' in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
: ... In instance t
|
||||
22 | shortreal sr;
|
||||
| ^~
|
||||
%Error: t/t_struct_contents_bad.v:23:19: Unpacked data type 'real' in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
: ... In instance t
|
||||
23 | realtime rt;
|
||||
| ^~
|
||||
%Error: t/t_struct_contents_bad.v:24:19: Unpacked data type 'chandle' in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
: ... In instance t
|
||||
24 | chandle ch;
|
||||
| ^~
|
||||
%Error: t/t_struct_contents_bad.v:25:19: Unpacked data type 'string' in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
: ... In instance t
|
||||
25 | string s;
|
||||
| ^
|
||||
%Error: t/t_struct_contents_bad.v:26:19: Unpacked data type 'event' in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
: ... In instance t
|
||||
26 | event e;
|
||||
| ^
|
||||
%Error: t/t_struct_contents_bad.v:27:25: Unpacked data type 'STRUCTDTYPE 't.struct_unpacked_t'' in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
: ... In instance t
|
||||
27 | struct_unpacked_t sp;
|
||||
| ^~
|
||||
%Error: t/t_struct_contents_bad.v:28:24: Unpacked data type 'UNIONDTYPE 't.union_unpacked_t'' in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
: ... In instance t
|
||||
28 | union_unpacked_t up;
|
||||
| ^~
|
||||
%Error: t/t_struct_contents_bad.v:29:11: Unpacked data type 'int$[0:1]' in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
: ... In instance t
|
||||
29 | int uarray[2];
|
||||
| ^~~~~~
|
||||
%Error: t/t_struct_contents_bad.v:30:11: Unpacked data type 'CLASSREFDTYPE 'Cls'' in packed struct/union (IEEE 1800-2017 7.2.1)
|
||||
: ... In instance t
|
||||
30 | Cls c;
|
||||
| ^
|
||||
%Error: Exiting due to
|
19
test_regress/t/t_struct_contents_bad.pl
Executable file
19
test_regress/t/t_struct_contents_bad.pl
Executable file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 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(linter => 1);
|
||||
|
||||
lint(
|
||||
fails => 1,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
37
test_regress/t/t_struct_contents_bad.v
Normal file
37
test_regress/t/t_struct_contents_bad.v
Normal file
@ -0,0 +1,37 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2023 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t(/*AUTOARG*/);
|
||||
|
||||
typedef enum logic [1:0] { ZERO, ONE } enum_t;
|
||||
|
||||
typedef struct { bit a; } struct_unpacked_t;
|
||||
typedef union { bit a; } union_unpacked_t;
|
||||
|
||||
class Cls;
|
||||
bit a;
|
||||
endclass
|
||||
|
||||
// IEEE 1800-2017 7.2.1
|
||||
typedef struct packed {
|
||||
real r; // BAD
|
||||
// verilator lint_off SHORTREAL
|
||||
shortreal sr; // BAD
|
||||
realtime rt; // BAD
|
||||
chandle ch; // BAD
|
||||
string s; // BAD
|
||||
event e; // BAD
|
||||
struct_unpacked_t sp; // BAD
|
||||
union_unpacked_t up; // BAD
|
||||
int uarray[2]; // BAD
|
||||
Cls c; // BAd
|
||||
} illegal_t;
|
||||
|
||||
initial begin
|
||||
$stop;
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user