Support parameter forward types.
This commit is contained in:
parent
f74c67da46
commit
ad08302e5f
1
Changes
1
Changes
|
@ -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).
|
||||
|
|
27
src/V3Ast.h
27
src/V3Ast.h
|
@ -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 {
|
||||
|
|
|
@ -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 "[ $ ]"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -12,7 +12,7 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('simulator')
|
||||
|
||||
signal.alarm(5) # 5s timeout
|
||||
signal.alarm(15) # 15s timeout
|
||||
|
||||
test.compile()
|
||||
|
||||
|
|
|
@ -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
|
|
@ -11,6 +11,6 @@ import vltest_bootstrap
|
|||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.lint(fails=True, expect_filename=test.golden_filename)
|
||||
test.lint()
|
||||
|
||||
test.passes()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
Loading…
Reference in New Issue