Fix typedef derived from type defined inside interface (#3441) (#6776)

This commit is contained in:
em2machine 2025-12-08 21:36:21 +01:00 committed by GitHub
parent 7e55c62cac
commit d0a5da2445
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 707 additions and 37 deletions

View File

@ -1177,7 +1177,6 @@ class AstRefDType final : public AstNodeDType {
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Data type references
// @astgen ptr := m_classOrPackagep : Optional[AstNodeModule] // Class/package defined in
string m_name; // Name of an AstTypedef
string m_ifacePortName; // Name of pre-dot interface port identifier
public:
AstRefDType(FileLine* fl, const string& name)
: ASTGEN_SUPER_RefDType(fl)
@ -1194,11 +1193,6 @@ public:
this->typeofp(typeofp);
if (AstNodeDType* const dtp = VN_CAST(typeofp, NodeDType)) refDTypep(dtp);
}
class FlagIfaceTypedef {};
AstRefDType(FileLine* fl, FlagIfaceTypedef, const string& ifc, const string& name)
: ASTGEN_SUPER_RefDType(fl)
, m_name{name}
, m_ifacePortName{ifc} {}
ASTGEN_MEMBERS_AstRefDType;
// METHODS
bool sameNode(const AstNode* samep) const override {
@ -1213,7 +1207,6 @@ public:
void dumpJson(std::ostream& str = std::cout) const override;
void dumpSmall(std::ostream& str) const override;
string name() const override VL_MT_STABLE { return m_name; }
string ifacePortName() const { return m_ifacePortName; }
string prettyDTypeName(bool full) const override {
return subDTypep() ? prettyName(subDTypep()->prettyDTypeName(full)) : prettyName();
}

View File

@ -2328,14 +2328,10 @@ void AstRefDType::dump(std::ostream& str) const {
s_recursing = false;
}
} else {
if (!ifacePortName().empty()) str << " ifcPort=" << ifacePortName();
str << " -> UNLINKED";
}
}
void AstRefDType::dumpJson(std::ostream& str) const {
if (!ifacePortName().empty()) dumpJsonStr(str, "ifcPortName", ifacePortName());
dumpJsonGen(str);
}
void AstRefDType::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
void AstRefDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);

View File

@ -5309,18 +5309,18 @@ class LinkDotResolveVisitor final : public VNVisitor {
const VSymEnt* foundp;
if (nodep->classOrPackagep()) {
foundp = m_statep->getNodeSym(nodep->classOrPackagep())->findIdFlat(nodep->name());
} else if (!nodep->ifacePortName().empty()) { // Interface typedef
nodep->v3error("Unsupported: SystemVerilog 2005 interface typedef");
return;
} else if (m_ds.m_dotPos == DP_FIRST || m_ds.m_dotPos == DP_NONE) {
foundp = m_curSymp->findIdFallback(nodep->name());
} else {
//foundp = m_curSymp->findIdFlat(nodep->name());
// Use dotSymp if set (e.g., for captured interface typedefs), else curSymp
VSymEnt* const lookupSymp = m_ds.m_dotSymp ? m_ds.m_dotSymp : m_curSymp;
foundp = lookupSymp->findIdFlat(nodep->name());
}
if (!foundp && ifaceCaptured && capturedTypedefp) {
if (ifaceCaptured && capturedTypedefp) {
// When we have a captured interface typedef context, use the captured typedef
// instead of any local lookup result. This handles the case where the local
// typedef has the same name as the interface typedef (e.g., `typedef if0.rq_t
// rq_t;`)
UINFO(9, indent() << "iface capture binding via captured typedef fallback name="
<< nodep->name() << " typedef=" << capturedTypedefp);
nodep->typedefp(capturedTypedefp);

View File

@ -390,9 +390,36 @@ class LinkParseVisitor final : public VNVisitor {
AstNode* dtypep = nodep->valuep();
if (dtypep) {
dtypep->unlinkFrBack();
// Transform right-associative Dot tree to left-associative
// This handles typedef with arrayed interface on first component:
// typedef if0[0].x_if0.rq_t my_t;
// Grammar produces: DOT(SELBIT, DOT(x_if0, rq_t))
// We need: DOT(DOT(SELBIT, x_if0), rq_t)
if (AstNodeExpr* exprp = VN_CAST(dtypep, NodeExpr)) {
AstDot* dotp = VN_CAST(exprp, Dot);
while (dotp) {
AstDot* rhsDotp = VN_CAST(dotp->rhsp(), Dot);
if (!rhsDotp) break;
FileLine* const fl = dotp->fileline();
const bool colon = dotp->colon();
AstNodeExpr* const lhs = VN_AS(dotp->lhsp()->unlinkFrBack(), NodeExpr);
AstNodeExpr* const rhsLhs
= VN_AS(rhsDotp->lhsp()->unlinkFrBack(), NodeExpr);
AstNodeExpr* const rhsRhs
= VN_AS(rhsDotp->rhsp()->unlinkFrBack(), NodeExpr);
FileLine* const rhsFl = rhsDotp->fileline();
const bool rhsColon = rhsDotp->colon();
AstDot* const newLhs = new AstDot{fl, colon, lhs, rhsLhs};
exprp = new AstDot{rhsFl, rhsColon, newLhs, rhsRhs};
VL_DO_DANGLING(dotp->deleteTree(), dotp);
dotp = VN_CAST(exprp, Dot);
}
dtypep = exprp;
}
} else {
dtypep = new AstVoidDType{nodep->fileline()};
}
AstNode* const newp = new AstParamTypeDType{
nodep->fileline(), nodep->varType(),
ptypep->fwdType(), nodep->name(),

View File

@ -2495,6 +2495,32 @@ type_declaration<nodep>: // ==IEEE: type_declaration
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ AstNodeDType* const dtp = $2;
$$ = GRAMMARP->createTypedef($<fl>3, *$3, $5, dtp, $4); }
// IEEE 1800-2017 6.18 typedef: dotted or arrayed type identifier
// Handles interface typedef references like if0.rq_t and if0[0].rq_t (arrays allowed after first component)
| yTYPEDEF idDottedOrArrayed
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ VARRESET_NONLIST(LPARAM);
AstParseTypeDType* const ptypep = new AstParseTypeDType{$<fl>2, VFwdType::NONE};
VARDTYPE(ptypep);
AstVar* const varp = VARDONEA($<fl>3, *$3, $4, $5);
// idDottedOrArrayed produces Dot/SelBit tree for hierarchical refs like if0[0].rq_t
varp->valuep($2);
$$ = varp; }
// IEEE 1800-2017 6.18 typedef with hierarchical type identifier
// Special-case array on first component requiring a '.' after ']' to disambiguate from packed dims
// Examples: typedef if0[0].rq_t my_t; typedef if0[0].x_if.rq_t my_t;
| yTYPEDEF id '[' expr ']' '.' idDottedSelMore
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ VARRESET_NONLIST(LPARAM);
AstParseTypeDType* const ptypep = new AstParseTypeDType{$<fl>2, VFwdType::NONE};
VARDTYPE(ptypep);
AstVar* const varp = VARDONEA($<fl>8, *$8, $9, $10);
AstNodeExpr* const arrp = new AstSelBit{$3, new AstParseRef{$<fl>2, *$2, nullptr, nullptr}, $4};
varp->valuep(new AstDot{$6, false, arrp, $7});
$$ = varp; }
| yTYPEDEF packageClassScope idAny packed_dimensionListE
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ AstRefDType* const refp = new AstRefDType{$<fl>3, *$3, $2, nullptr};
@ -2505,20 +2531,36 @@ type_declaration<nodep>: // ==IEEE: type_declaration
{ AstRefDType* const refp = new AstRefDType{$<fl>3, *$3, $2, $4};
AstNodeDType* const dtp = GRAMMARP->createArray(refp, $5, true);
$$ = GRAMMARP->createTypedef($<fl>6, *$6, $8, dtp, $7); }
| yTYPEDEF idAny packed_dimensionListE
// Type alias without packed dimensions: typedef existing_t new_t;
| yTYPEDEF idAny idAny variable_dimensionListE dtypeAttrListE ';'
{ AstRefDType* const refp = new AstRefDType{$<fl>2, *$2, nullptr, nullptr};
$$ = GRAMMARP->createTypedef($<fl>3, *$3, $5, refp, $4); }
// IEEE 1800-2017 6.18.2 typedef with packed dimensions on an existing type identifier
// Disambiguated from interface array access by requiring ':' inside the brackets
// (applies to both plain identifiers and type identifiers)
| yTYPEDEF id '[' constExpr ':' constExpr ']' packed_dimensionListE
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ AstRefDType* const refp = new AstRefDType{$<fl>2, *$2, nullptr, nullptr};
AstNodeDType* const dtp = GRAMMARP->createArray(refp, $3, true);
$$ = GRAMMARP->createTypedef($<fl>4, *$4, $6, dtp, $5); }
AstNodeRange* const rangep = new AstRange{$3, $4, $6};
AstNodeDType* const dtp = GRAMMARP->createArray(refp, addNextNull(rangep, $8), true);
$$ = GRAMMARP->createTypedef($<fl>9, *$9, $11, dtp, $10); }
// Same as above but for type identifiers (parameter types, etc.)
| yTYPEDEF idType '[' constExpr ':' constExpr ']' packed_dimensionListE
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ AstRefDType* const refp = new AstRefDType{$<fl>2, *$2, nullptr, nullptr};
AstNodeRange* const rangep = new AstRange{$3, $4, $6};
AstNodeDType* const dtp = GRAMMARP->createArray(refp, addNextNull(rangep, $8), true);
$$ = GRAMMARP->createTypedef($<fl>9, *$9, $11, dtp, $10); }
| yTYPEDEF idAny parameter_value_assignmentClass packed_dimensionListE
/*cont*/ idAny variable_dimensionListE dtypeAttrListE ';'
{ AstRefDType* const refp = new AstRefDType{$<fl>2, *$2, nullptr, $3};
AstNodeDType* const dtp = GRAMMARP->createArray(refp, $4, true);
$$ = GRAMMARP->createTypedef($<fl>5, *$5, $7, dtp, $6); }
// //
| yTYPEDEF idAny/*interface_port*/ '.' idAny/*type*/ idAny/*type*/ dtypeAttrListE ';'
{ AstRefDType* const refp = new AstRefDType{$<fl>2, AstRefDType::FlagIfaceTypedef{}, *$2, *$4};
$$ = GRAMMARP->createTypedef($<fl>5, *$5, $6, refp, nullptr); }
// // idAny as also allows redeclaring same typedef again
| yTYPEDEF idAny ';' { $$ = GRAMMARP->createTypedefFwd($<fl>2, *$2, VFwdType::NONE); }
// // IEEE: expanded forward_type to prevent conflict
@ -5995,6 +6037,16 @@ idClassSelForeach<nodeExprp>:
| packageClassScope idDottedForeach { $$ = new AstDot{$<fl>2, true, $1, $2}; }
;
// Dotted identifier for typedef - must have at least one '.'
// First component is plain id or id with array index, subsequent components can have arrays
idDottedOrArrayed<nodeExprp>:
id '.' idArrayed
{ $$ = new AstDot{$2, false, new AstParseRef{$<fl>1, *$1, nullptr, nullptr}, $3}; }
| idDottedOrArrayed '.' idArrayed
{ $$ = new AstDot{$2, false, $1, $3}; }
;
idDotted<nodeExprp>:
yD_ROOT '.' idDottedMore
{ $$ = new AstDot{$2, false, new AstParseRef{$<fl>1, "$root"}, $3}; }

View File

@ -11,9 +11,7 @@ import vltest_bootstrap
test.scenarios('simulator_st')
test.compile(verilator_flags2=['--binary'],
fails=test.vlt_all,
expect_filename=test.golden_filename)
test.compile(verilator_flags2=['--binary'])
if not test.vlt_all:
test.execute()

View File

@ -11,9 +11,7 @@ import vltest_bootstrap
test.scenarios('simulator_st')
test.compile(verilator_flags2=['--binary'],
fails=test.vlt_all,
expect_filename=test.golden_filename)
test.compile(verilator_flags2=['--binary'])
if not test.vlt_all:
test.execute()

View File

@ -1,5 +1,5 @@
%Error: t/t_interface_typedef3.v:22:11: Unsupported: SystemVerilog 2005 interface typedef
%Error: t/t_interface_typedef3.v:22:19: Expecting a data type, not DOT: ''
22 | typedef iface_mp.choice_t tdef_t;
| ^~~~~~~~
| ^
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -1,11 +1,14 @@
%Error: t/t_interface_typedef_bad.v:15:11: Unsupported: SystemVerilog 2005 interface typedef
%Error: t/t_interface_typedef_bad.v:15:11: Can't find definition of scope/variable: 'not_found'
15 | typedef not_found.choice_t choice1_t;
| ^~~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_interface_typedef_bad.v:16:11: Unsupported: SystemVerilog 2005 interface typedef
%Error: t/t_interface_typedef_bad.v:15:20: Expecting a data type, not a constant: 0
15 | typedef not_found.choice_t choice1_t;
| ^
%Error: t/t_interface_typedef_bad.v:16:12: Expecting a data type, not DOT: ''
16 | typedef i.not_found_t choice2_t;
| ^
%Error: t/t_interface_typedef_bad.v:17:11: Unsupported: SystemVerilog 2005 interface typedef
| ^
%Error: t/t_interface_typedef_bad.v:17:19: Expecting a data type, not MEMBERSEL: 'x_t'
17 | typedef not_ifc.x_t choice3_t;
| ^~~~~~~
| ^~~
%Error: Exiting due to

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,47 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
//
// assign localparam from nested interface typedef
//
interface x_if #(
parameter int p_awidth = 4
)();
typedef struct packed {
logic [p_awidth-1:0] addr;
} rq_t;
endinterface
interface y_if #(
parameter int p_dwidth = 7
)();
typedef struct packed {
logic [p_dwidth-1:0] data;
} rs_t;
endinterface
interface z_if #(
parameter int p_awidth = 3
,parameter int p_dwidth = 9
);
x_if #(p_awidth) x_if0();
y_if #(p_dwidth) y_if0();
endinterface
module top();
z_if #(.p_awidth(16) ,.p_dwidth(8)) if0();
localparam type rq_t = if0.x_if0.rq_t;
rq_t rq;
initial begin
#1;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,55 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
//
// assign localparam from interface typedef, single level nesting
//
`define stop $stop
`define checkh(gotv,expv) \
do if ((gotv) !== (expv)) begin \
$write("%%Error: %s:%0d: got=%0h exp=%0h\n", \
`__FILE__,`__LINE__, (gotv), (expv)); \
`stop; \
end while(0);
interface x_if #(
parameter int p_awidth = 4
,parameter int p_dwidth = 7
)();
typedef struct packed {
logic [p_awidth-1:0] addr;
logic [p_dwidth-1:0] data;
} rq_t;
typedef struct packed {
logic [p_dwidth-1:0] data;
} rs_t;
endinterface
module top();
x_if #(
.p_awidth(16)
,.p_dwidth(8)
) if0();
typedef if0.rq_t p0_rq_t;
p0_rq_t rq;
always_comb begin
rq.addr = 'h1234;
rq.data = 'h37;
end
initial begin
#1;
`checkh(rq.addr, 16'h1234);
`checkh(rq.data, 8'h37);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,29 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
//
interface x_if #(
parameter int a_width = 3
)();
typedef struct packed {
logic [a_width-1:0] addr;
} rq_t;
endinterface
module top();
x_if #(
.a_width(8)
) if0();
typedef if0.rq_t p0_t;
initial begin
#1;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,65 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
//
// assign localparam from interface typedef, single level nesting
//
`define stop $stop
`define checkd(gotv,expv) \
do if ((gotv) !== (expv)) begin \
$write("%%Error: %s:%0d: got=%0d exp=%0d\n", \
`__FILE__,`__LINE__, (gotv), (expv)); \
`stop; \
end while(0);
`define checkh(gotv,expv) \
do if ((gotv) !== (expv)) begin \
$write("%%Error: %s:%0d: got=%0h exp=%0h\n", \
`__FILE__,`__LINE__, (gotv), (expv)); \
`stop; \
end while(0);
interface x_if #(
parameter int p_awidth = 4
,parameter int p_dwidth = 7
)();
localparam int Bits = p_awidth + p_dwidth;
typedef struct packed {
logic [p_awidth-1:0] addr;
logic [p_dwidth-1:0] data;
} rq_t;
endinterface
interface y_if #(
parameter int p_awidth = 4
,parameter int p_dwidth = 7
)();
x_if #(.p_awidth(p_awidth), .p_dwidth(p_dwidth)) x_if_a[2] ();
endinterface
module top();
y_if #(
.p_awidth(16)
,.p_dwidth(8)
) y_if0 ();
typedef y_if0.x_if_a[0].rq_t rq_t;
rq_t rq;
always_comb begin
rq.addr = 'h1234;
rq.data = 'h37;
end
initial begin
#1;
`checkh(rq.addr,16'h1234);
`checkh(rq.data,8'h37);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,82 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
//
// assign localparam from interface typedef, single level nesting
//
`define stop $stop
`define checkd(gotv,expv) \
do if ((gotv) !== (expv)) begin \
$write("%%Error: %s:%0d: got=%0d exp=%0d\n", \
`__FILE__,`__LINE__, (gotv), (expv)); \
`stop; \
end while(0);
`define checkh(gotv,expv) \
do if ((gotv) !== (expv)) begin \
$write("%%Error: %s:%0d: got=%0h exp=%0h\n", \
`__FILE__,`__LINE__, (gotv), (expv)); \
`stop; \
end while(0);
interface x_if #(
parameter int p_awidth = 4
)();
typedef struct packed {
logic [p_awidth-1:0] addr;
} rq_t;
endinterface
interface y_if #(
parameter int p_dwidth = 7
)();
typedef struct packed {
logic [p_dwidth-1:0] data;
} rs_t;
endinterface
interface z_if #(
parameter int p_awidth = 3
,parameter int p_dwidth = 9
);
x_if #(p_awidth) x_if0();
y_if #(p_dwidth) y_if0();
endinterface
module a_top(
z_if z_if0
);
typedef z_if0.x_if0.rq_t rq_t;
typedef z_if0.y_if0.rs_t rs_t;
rq_t rq;
rs_t rs;
always_comb begin
rq.addr = 'h1234;
rs.data = 'ha5;
end
initial begin
#1;
`checkh(rq.addr,16'h1234);
`checkh(rs.data,8'ha5);
end
endmodule
module top();
z_if #(.p_awidth(16) ,.p_dwidth(8)) z_if0();
a_top a_top(z_if0);
initial begin
#1;
#1;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,70 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
//
// assign localparam from interface typedef, single level nesting
//
`define stop $stop
`define checkd(gotv,expv) \
do if ((gotv) !== (expv)) begin \
$write("%%Error: %s:%0d: got=%0d exp=%0d\n", \
`__FILE__,`__LINE__, (gotv), (expv)); \
`stop; \
end while(0);
`define checkh(gotv,expv) \
do if ((gotv) !== (expv)) begin \
$write("%%Error: %s:%0d: got=%0h exp=%0h\n", \
`__FILE__,`__LINE__, (gotv), (expv)); \
`stop; \
end while(0);
interface x_if #(
parameter int p_awidth = 4
)();
typedef struct packed {
logic [p_awidth-1:0] addr;
} rq_t;
endinterface
interface y_if #(
parameter int p_dwidth = 7
)();
typedef struct packed {
logic [p_dwidth-1:0] data;
} rs_t;
endinterface
interface z_if #(
parameter int p_awidth = 3
,parameter int p_dwidth = 9
);
x_if #(p_awidth) x_if0();
y_if #(p_dwidth) y_if0();
endinterface
module top();
z_if #(.p_awidth(16) ,.p_dwidth(8)) if0();
typedef if0.x_if0.rq_t rq_t;
typedef if0.y_if0.rs_t rs_t;
rq_t rq;
rs_t rs;
always_comb begin
rq.addr = 'h1234;
rs.data = 'ha5;
end
initial begin
#1;
`checkh(rq.addr,16'h1234);
`checkh(rs.data,8'ha5);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,66 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
//
// assign localparam from interface typedef, single level nesting
//
`define stop $stop
`define checkd(gotv,expv) \
do if ((gotv) !== (expv)) begin \
$write("%%Error: %s:%0d: got=%0d exp=%0d\n", \
`__FILE__,`__LINE__, (gotv), (expv)); \
`stop; \
end while(0);
`define checkh(gotv,expv) \
do if ((gotv) !== (expv)) begin \
$write("%%Error: %s:%0d: got=%0h exp=%0h\n", \
`__FILE__,`__LINE__, (gotv), (expv)); \
`stop; \
end while(0);
interface x_if #(
parameter int p_awidth = 4
)();
typedef struct packed {
logic [p_awidth-1:0] addr;
} rq_t;
endinterface
interface y_if #(
parameter int p_dwidth = 7
)();
typedef struct packed {
logic [p_dwidth-1:0] data;
} rs_t;
endinterface
interface z_if #(
parameter int p_awidth = 3
,parameter int p_dwidth = 9
);
x_if #(p_awidth) x_if0();
y_if #(p_dwidth) y_if0();
endinterface
module top();
z_if #(.p_awidth(16) ,.p_dwidth(8)) if0 [2] ();
typedef if0[0].x_if0.rq_t rq_t;
rq_t rq;
always_comb begin
rq.addr = 'h1234;
end
initial begin
#1;
`checkh(rq.addr,16'h1234);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,45 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
//
// Chained typedef aliases from an interface typedef
`define stop $stop
`define checkh(gotv,expv) \
do if ((gotv) !== (expv)) begin \
$write("%%Error: %s:%0d: got=%0h exp=%0h\n", \
`__FILE__,`__LINE__, (gotv), (expv)); \
`stop; \
end while(0);
interface x_if #(
parameter int p_awidth = 4
)();
typedef struct packed {
logic [p_awidth-1:0] addr;
} rq_t;
endinterface
module top();
x_if #(.p_awidth(16)) if0();
// First alias of interface typedef
typedef if0.rq_t my_rq_t;
// Second alias of the alias
typedef my_rq_t my_rq2_t;
my_rq2_t rq;
always_comb begin
rq.addr = 'h1234;
end
initial begin
#1;
`checkh(rq.addr,16'h1234);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule