Support parameter forward types.

This commit is contained in:
Wilson Snyder 2025-05-19 08:35:27 -04:00
parent f74c67da46
commit ad08302e5f
14 changed files with 192 additions and 60 deletions

View File

@ -17,6 +17,7 @@ Verilator 5.037 devel
* Support constrained random for associative arrays (#5985) (#5986). [Yilou Wang]
* Support assignments to concatenations with impure RHS (#6002). [Ryszard Rozak, Antmicro Ltd.]
* Support SARIF JSON diagnostic output with `--diagnostics-sarif`. (#6017)
* Support parameter forward types.
* Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu]
* Add PROCINITASSIGN on initial assignments to process variables (#2481). [Niraj Menon]
* Fix filename backslash escapes in C code (#5947).

View File

@ -287,6 +287,33 @@ public:
// ######################################################################
class VFwdType final {
public:
enum en : uint8_t { NONE, ENUM, STRUCT, UNION, CLASS, INTERFACE_CLASS };
enum en m_e;
const char* ascii() const {
static const char* const names[]
= {"none", "enum", "struct", "union", "class", "interface class"};
return names[m_e];
}
VFwdType()
: m_e{NONE} {}
// cppcheck-suppress noExplicitConstructor
constexpr VFwdType(en _e)
: m_e{_e} {}
explicit VFwdType(int _e)
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
constexpr operator en() const { return m_e; }
};
constexpr bool operator==(const VFwdType& lhs, const VFwdType& rhs) { return lhs.m_e == rhs.m_e; }
constexpr bool operator==(const VFwdType& lhs, VFwdType::en rhs) { return lhs.m_e == rhs; }
constexpr bool operator==(VFwdType::en lhs, const VFwdType& rhs) { return lhs == rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const VFwdType& rhs) {
return os << rhs.ascii();
}
// ######################################################################
class VSigning final {
public:
enum en : uint8_t {

View File

@ -1006,12 +1006,14 @@ class AstParamTypeDType final : public AstNodeDType {
// A parameter type statement; much like a var or typedef
// @astgen op1 := childDTypep : Optional[AstNodeDType]
const VVarType m_varType; // Type of variable (for localparam vs. param)
const VFwdType m_fwdType; // Forward type for lint check
string m_name; // Name of variable
public:
AstParamTypeDType(FileLine* fl, VVarType type, const string& name, VFlagChildDType,
AstNodeDType* dtp)
AstParamTypeDType(FileLine* fl, VVarType type, VFwdType fwdType, const string& name,
VFlagChildDType, AstNodeDType* dtp)
: ASTGEN_SUPER_ParamTypeDType(fl)
, m_varType{type}
, m_fwdType{fwdType}
, m_name{name} {
childDTypep(dtp); // Only for parser
dtypep(nullptr); // V3Width will resolve
@ -1036,6 +1038,7 @@ public:
bool hasDType() const override VL_MT_SAFE { return true; }
void name(const string& flag) override { m_name = flag; }
VVarType varType() const { return m_varType; } // * = Type of variable
VFwdType fwdType() const { return m_fwdType; }
bool isParam() const { return true; }
bool isGParam() const { return (varType() == VVarType::GPARAM); }
bool isCompound() const override {
@ -1047,9 +1050,11 @@ class AstParseTypeDType final : public AstNodeDType {
// Parents: VAR
// During parsing, this indicates the type of a parameter is a "parameter type"
// e.g. the data type is a container of any data type
const VFwdType m_fwdType; // Forward type for lint check
public:
explicit AstParseTypeDType(FileLine* fl)
: ASTGEN_SUPER_ParseTypeDType(fl) {}
explicit AstParseTypeDType(FileLine* fl, VFwdType fwdType = VFwdType::NONE)
: ASTGEN_SUPER_ParseTypeDType(fl)
, m_fwdType{fwdType} {}
ASTGEN_MEMBERS_AstParseTypeDType;
AstNodeDType* dtypep() const VL_MT_STABLE { return nullptr; }
// METHODS
@ -1061,6 +1066,7 @@ public:
v3fatalSrc("call isCompound on subdata type, not reference");
return false;
}
VFwdType fwdType() const { return m_fwdType; }
};
class AstQueueDType final : public AstNodeDType {
// Queue array data type, ie "[ $ ]"

View File

@ -322,7 +322,7 @@ class LinkParseVisitor final : public VNVisitor {
nodep->v3warn(NEWERSTD,
"Parameter requires default value, or use IEEE 1800-2009 or later.");
}
if (VN_IS(nodep->subDTypep(), ParseTypeDType)) {
if (AstParseTypeDType* const ptypep = VN_CAST(nodep->subDTypep(), ParseTypeDType)) {
// It's a parameter type. Use a different node type for this.
AstNode* dtypep = nodep->valuep();
if (dtypep) {
@ -331,8 +331,9 @@ class LinkParseVisitor final : public VNVisitor {
dtypep = new AstVoidDType{nodep->fileline()};
}
AstNode* const newp = new AstParamTypeDType{
nodep->fileline(), nodep->varType(), nodep->name(), VFlagChildDType{},
new AstRequireDType{nodep->fileline(), dtypep}};
nodep->fileline(), nodep->varType(),
ptypep->fwdType(), nodep->name(),
VFlagChildDType{}, new AstRequireDType{nodep->fileline(), dtypep}};
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
return;

View File

@ -782,6 +782,24 @@ class ParamProcessor final {
// Constify may have caused pinp->exprp to change
rawTypep = VN_AS(pinp->exprp(), NodeDType);
exprp = rawTypep->skipRefToNonRefp();
bool ok = true;
switch (modvarp->fwdType()) {
case VFwdType::NONE: ok = true; break;
case VFwdType::ENUM: ok = VN_IS(exprp, EnumDType); break;
case VFwdType::STRUCT: ok = VN_IS(exprp, StructDType); break;
case VFwdType::UNION: ok = VN_IS(exprp, UnionDType); break;
case VFwdType::CLASS: ok = VN_IS(exprp, ClassRefDType); break;
case VFwdType::INTERFACE_CLASS: // TODO: Over permissive for now:
ok = VN_IS(exprp, ClassRefDType);
break;
default: modvarp->v3fatalSrc("Bad case");
}
if (!ok) {
pinp->v3error("Parameter type expression type "
<< exprp->prettyDTypeNameQ()
<< " violates parameter's forwarding type '"
<< modvarp->fwdType().ascii() << "'");
}
if (exprp->similarDType(origp)) {
// Setting parameter to its default value. Just ignore it.
// This prevents making additional modules, and makes coverage more

View File

@ -125,6 +125,7 @@ struct V3ParseBisonYYSType final {
VAttrType::en attrtypeen;
VAssertType::en asserttypeen;
VAssertDirectiveType::en assertdirectivetypeen;
VFwdType::en fwdtype;
VLifetime::en lifetime;
VStrength::en strength;

View File

@ -1916,9 +1916,11 @@ parameter_declarationFront: // IEEE: local_ or parameter_declaration w/o ass
parameter_declarationTypeFront: // IEEE: local_ or parameter_declaration w/o assignment
// // Front must execute first so VARDTYPE is ready before list of vars
varParamReset yTYPE__ETC { /*VARRESET-in-varParam*/ VARDTYPE(new AstParseTypeDType{$2}); }
| varParamReset yTYPE__ETC forward_type { /*VARRESET-in-varParam*/ VARDTYPE(new AstParseTypeDType{$2});
BBUNSUP($<fl>1, "Unsupported: 'parameter type' forward type"); }
varParamReset yTYPE__ETC
{ /*VARRESET-in-varParam*/ VARDTYPE(new AstParseTypeDType{$2}); }
| varParamReset yTYPE__ETC forward_type
{ /*VARRESET-in-varParam*/
AstNodeDType* const dtp = new AstParseTypeDType{$2, $3}; VARDTYPE(dtp); }
;
parameter_port_declarationFrontE: // IEEE: local_ or parameter_port_declaration w/o assignment
@ -1939,20 +1941,26 @@ parameter_port_declarationTypeFrontE: // IEEE: parameter_port_declaration w/o as
// // IEEE: parameter_declaration (minus assignment)
// // IEEE: local_parameter_declaration (minus assignment)
// // Front must execute first so VARDTYPE is ready before list of vars
varParamReset yTYPE__ETC { /*VARRESET-in-varParam*/ VARDTYPE(new AstParseTypeDType{$2}); }
| varParamReset yTYPE__ETC forward_type { /*VARRESET-in-varParam*/ VARDTYPE(new AstParseTypeDType{$2});
BBUNSUP($<fl>1, "Unsupported: 'parameter type' forward type"); }
| yTYPE__ETC { /*VARRESET-in-varParam*/ VARDTYPE(new AstParseTypeDType{$1}); }
| yTYPE__ETC forward_type { /*VARRESET-in-varParam*/ VARDTYPE(new AstParseTypeDType{$1});
BBUNSUP($<fl>1, "Unsupported: 'parameter type' forward type"); }
varParamReset yTYPE__ETC
{ /*VARRESET-in-varParam*/
AstNodeDType* const dtp = new AstParseTypeDType{$2}; VARDTYPE(dtp); }
| varParamReset yTYPE__ETC forward_type
{ /*VARRESET-in-varParam*/
AstNodeDType* const dtp = new AstParseTypeDType{$2, $3}; VARDTYPE(dtp); }
| yTYPE__ETC
{ /*VARRESET-in-varParam*/
AstNodeDType* const dtp = new AstParseTypeDType{$1}; VARDTYPE(dtp); }
| yTYPE__ETC forward_type
{ /*VARRESET-in-varParam*/
AstNodeDType* const dtp = new AstParseTypeDType{$1, $2}; VARDTYPE(dtp); }
;
forward_type: // ==IEEE: forward_type
yENUM { }
| ySTRUCT { }
| yUNION { }
| yCLASS { }
| yINTERFACE yCLASS { }
forward_type<fwdtype>: // ==IEEE: forward_type
yENUM { $$ = VFwdType::ENUM; }
| ySTRUCT { $$ = VFwdType::STRUCT; }
| yUNION { $$ = VFwdType::UNION; }
| yCLASS { $$ = VFwdType::CLASS; }
| yINTERFACE yCLASS { $$ = VFwdType::INTERFACE_CLASS; }
;
net_declaration<nodep>: // IEEE: net_declaration - excluding implict

View File

@ -12,7 +12,7 @@ import vltest_bootstrap
test.scenarios('simulator')
signal.alarm(5) # 5s timeout
signal.alarm(15) # 15s timeout
test.compile()

View File

@ -1,32 +0,0 @@
%Error-UNSUPPORTED: t/t_param_type_fwd.v:10:4: Unsupported: 'parameter type' forward type
10 | parameter type enum E_t;
| ^~~~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_param_type_fwd.v:11:4: Unsupported: 'parameter type' forward type
11 | parameter type struct S_t;
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_param_type_fwd.v:12:4: Unsupported: 'parameter type' forward type
12 | parameter type union U_t;
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_param_type_fwd.v:13:4: Unsupported: 'parameter type' forward type
13 | parameter type class C_t;
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_param_type_fwd.v:14:4: Unsupported: 'parameter type' forward type
14 | parameter type interface class IC_t;
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_param_type_fwd.v:17:13: Unsupported: 'parameter type' forward type
17 | class Cls #(parameter type enum E_t,
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_param_type_fwd.v:18:13: Unsupported: 'parameter type' forward type
18 | parameter type struct S_t,
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_param_type_fwd.v:19:13: Unsupported: 'parameter type' forward type
19 | parameter type union U_t,
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_param_type_fwd.v:20:13: Unsupported: 'parameter type' forward type
20 | parameter type class C_t,
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_param_type_fwd.v:21:13: Unsupported: 'parameter type' forward type
21 | parameter type interface class IC_t);
| ^~~~~~~~~
%Error: Exiting due to

View File

@ -11,6 +11,6 @@ import vltest_bootstrap
test.scenarios('vlt')
test.lint(fails=True, expect_filename=test.golden_filename)
test.lint()
test.passes()

View File

@ -4,9 +4,19 @@
// without warranty, 2024 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
// Test for trace file interface aliasing
typedef enum { ONE } e_t;
module m;
typedef struct { int m_i; } s_t;
typedef union { int m_i; } u_t;
class c_t;
endclass
interface class ic_t;
endclass
module sub;
parameter type enum E_t;
parameter type struct S_t;
parameter type union U_t;
@ -21,6 +31,10 @@ class Cls #(parameter type enum E_t,
parameter type interface class IC_t);
endclass
module t (/*AUTOARG*/);
// TODO proper test
module t;
sub #(.E_t(e_t), .S_t(s_t), .U_t(u_t), .C_t(c_t), .IC_t(ic_t)) sub();
Cls #(.E_t(e_t), .S_t(s_t), .U_t(u_t), .C_t(c_t), .IC_t(ic_t)) c;
initial begin
c = new;
end
endmodule

View File

@ -0,0 +1,42 @@
%Error: t/t_param_type_fwd_bad.v:25:11: Parameter type expression type 'int' violates parameter's forwarding type 'enum'
: ... note: In instance 't'
25 | sub #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) sub();
| ^~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_param_type_fwd_bad.v:25:24: Parameter type expression type 'int' violates parameter's forwarding type 'struct'
: ... note: In instance 't'
25 | sub #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) sub();
| ^~~
%Error: t/t_param_type_fwd_bad.v:25:37: Parameter type expression type 'int' violates parameter's forwarding type 'union'
: ... note: In instance 't'
25 | sub #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) sub();
| ^~~
%Error: t/t_param_type_fwd_bad.v:25:50: Parameter type expression type 'int' violates parameter's forwarding type 'class'
: ... note: In instance 't'
25 | sub #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) sub();
| ^~~
%Error: t/t_param_type_fwd_bad.v:25:63: Parameter type expression type 'int' violates parameter's forwarding type 'interface class'
: ... note: In instance 't'
25 | sub #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) sub();
| ^~~~
%Error: t/t_param_type_fwd_bad.v:26:11: Parameter type expression type 'int' violates parameter's forwarding type 'enum'
: ... note: In instance 't'
26 | Cls #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) c;
| ^~~
%Error: t/t_param_type_fwd_bad.v:26:24: Parameter type expression type 'int' violates parameter's forwarding type 'struct'
: ... note: In instance 't'
26 | Cls #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) c;
| ^~~
%Error: t/t_param_type_fwd_bad.v:26:37: Parameter type expression type 'int' violates parameter's forwarding type 'union'
: ... note: In instance 't'
26 | Cls #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) c;
| ^~~
%Error: t/t_param_type_fwd_bad.v:26:50: Parameter type expression type 'int' violates parameter's forwarding type 'class'
: ... note: In instance 't'
26 | Cls #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) c;
| ^~~
%Error: t/t_param_type_fwd_bad.v:26:63: Parameter type expression type 'int' violates parameter's forwarding type 'interface class'
: ... note: In instance 't'
26 | Cls #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) c;
| ^~~~
%Error: Exiting due to

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# 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
import vltest_bootstrap
test.scenarios('vlt')
test.lint(fails=True, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,30 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
typedef int int_t;
module sub;
parameter type enum E_t;
parameter type struct S_t;
parameter type union U_t;
parameter type class C_t;
parameter type interface class IC_t;
endmodule
class Cls #(parameter type enum E_t,
parameter type struct S_t,
parameter type union U_t,
parameter type class C_t,
parameter type interface class IC_t);
endclass
module t (/*AUTOARG*/);
sub #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) sub();
Cls #(.E_t(int_t), .S_t(int_t), .U_t(int_t), .C_t(int_t), .IC_t(int_t)) c;
initial begin
c = new;
end
endmodule