diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index 5ccec4121..4eafbbeae 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -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(); } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index b3dc686e9..b24a43252 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -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); diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 28c45d0ef..97d0359b6 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -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); diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 977260230..24330dacd 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -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(), diff --git a/src/verilog.y b/src/verilog.y index 7466e0c13..21d327c4b 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2495,6 +2495,32 @@ type_declaration: // ==IEEE: type_declaration /*cont*/ idAny variable_dimensionListE dtypeAttrListE ';' { AstNodeDType* const dtp = $2; $$ = GRAMMARP->createTypedef($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{$2, VFwdType::NONE}; + VARDTYPE(ptypep); + AstVar* const varp = VARDONEA($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{$2, VFwdType::NONE}; + VARDTYPE(ptypep); + AstVar* const varp = VARDONEA($8, *$8, $9, $10); + AstNodeExpr* const arrp = new AstSelBit{$3, new AstParseRef{$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{$3, *$3, $2, nullptr}; @@ -2505,20 +2531,36 @@ type_declaration: // ==IEEE: type_declaration { AstRefDType* const refp = new AstRefDType{$3, *$3, $2, $4}; AstNodeDType* const dtp = GRAMMARP->createArray(refp, $5, true); $$ = GRAMMARP->createTypedef($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{$2, *$2, nullptr, nullptr}; + $$ = GRAMMARP->createTypedef($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{$2, *$2, nullptr, nullptr}; - AstNodeDType* const dtp = GRAMMARP->createArray(refp, $3, true); - $$ = GRAMMARP->createTypedef($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($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{$2, *$2, nullptr, nullptr}; + AstNodeRange* const rangep = new AstRange{$3, $4, $6}; + AstNodeDType* const dtp = GRAMMARP->createArray(refp, addNextNull(rangep, $8), true); + $$ = GRAMMARP->createTypedef($9, *$9, $11, dtp, $10); } + | yTYPEDEF idAny parameter_value_assignmentClass packed_dimensionListE /*cont*/ idAny variable_dimensionListE dtypeAttrListE ';' { AstRefDType* const refp = new AstRefDType{$2, *$2, nullptr, $3}; AstNodeDType* const dtp = GRAMMARP->createArray(refp, $4, true); $$ = GRAMMARP->createTypedef($5, *$5, $7, dtp, $6); } - // // - | yTYPEDEF idAny/*interface_port*/ '.' idAny/*type*/ idAny/*type*/ dtypeAttrListE ';' - { AstRefDType* const refp = new AstRefDType{$2, AstRefDType::FlagIfaceTypedef{}, *$2, *$4}; - $$ = GRAMMARP->createTypedef($5, *$5, $6, refp, nullptr); } + // // idAny as also allows redeclaring same typedef again | yTYPEDEF idAny ';' { $$ = GRAMMARP->createTypedefFwd($2, *$2, VFwdType::NONE); } // // IEEE: expanded forward_type to prevent conflict @@ -5995,6 +6037,16 @@ idClassSelForeach: | packageClassScope idDottedForeach { $$ = new AstDot{$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: + id '.' idArrayed + { $$ = new AstDot{$2, false, new AstParseRef{$1, *$1, nullptr, nullptr}, $3}; } + | idDottedOrArrayed '.' idArrayed + { $$ = new AstDot{$2, false, $1, $3}; } + ; + idDotted: yD_ROOT '.' idDottedMore { $$ = new AstDot{$2, false, new AstParseRef{$1, "$root"}, $3}; } diff --git a/test_regress/t/t_interface_typedef.py b/test_regress/t/t_interface_typedef.py index da7d64435..62c547843 100755 --- a/test_regress/t/t_interface_typedef.py +++ b/test_regress/t/t_interface_typedef.py @@ -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() diff --git a/test_regress/t/t_interface_typedef2.py b/test_regress/t/t_interface_typedef2.py index da7d64435..62c547843 100755 --- a/test_regress/t/t_interface_typedef2.py +++ b/test_regress/t/t_interface_typedef2.py @@ -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() diff --git a/test_regress/t/t_interface_typedef3.out b/test_regress/t/t_interface_typedef3.out index 81f7b6d6c..9895ef810 100644 --- a/test_regress/t/t_interface_typedef3.out +++ b/test_regress/t/t_interface_typedef3.out @@ -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 diff --git a/test_regress/t/t_interface_typedef_bad.out b/test_regress/t/t_interface_typedef_bad.out index 1c91f464c..2a747ad1c 100644 --- a/test_regress/t/t_interface_typedef_bad.out +++ b/test_regress/t/t_interface_typedef_bad.out @@ -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 diff --git a/test_regress/t/t_lparam_assign_iface_typedef_nested6.py b/test_regress/t/t_lparam_assign_iface_typedef_nested6.py new file mode 100755 index 000000000..c6e56559a --- /dev/null +++ b/test_regress/t/t_lparam_assign_iface_typedef_nested6.py @@ -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() diff --git a/test_regress/t/t_lparam_assign_iface_typedef_nested6.v b/test_regress/t/t_lparam_assign_iface_typedef_nested6.v new file mode 100644 index 000000000..527fcee7c --- /dev/null +++ b/test_regress/t/t_lparam_assign_iface_typedef_nested6.v @@ -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 diff --git a/test_regress/t/t_typedef_iface_typedef.py b/test_regress/t/t_typedef_iface_typedef.py new file mode 100755 index 000000000..c6e56559a --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef.py @@ -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() diff --git a/test_regress/t/t_typedef_iface_typedef.v b/test_regress/t/t_typedef_iface_typedef.v new file mode 100644 index 000000000..8c799a496 --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef.v @@ -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 diff --git a/test_regress/t/t_typedef_iface_typedef2.py b/test_regress/t/t_typedef_iface_typedef2.py new file mode 100755 index 000000000..c6e56559a --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef2.py @@ -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() diff --git a/test_regress/t/t_typedef_iface_typedef2.v b/test_regress/t/t_typedef_iface_typedef2.v new file mode 100644 index 000000000..69078a9d4 --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef2.v @@ -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 diff --git a/test_regress/t/t_typedef_iface_typedef3.py b/test_regress/t/t_typedef_iface_typedef3.py new file mode 100755 index 000000000..c6e56559a --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef3.py @@ -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() diff --git a/test_regress/t/t_typedef_iface_typedef3.v b/test_regress/t/t_typedef_iface_typedef3.v new file mode 100644 index 000000000..1f91f0d3f --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef3.v @@ -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 diff --git a/test_regress/t/t_typedef_iface_typedef4.py b/test_regress/t/t_typedef_iface_typedef4.py new file mode 100755 index 000000000..c6e56559a --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef4.py @@ -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() diff --git a/test_regress/t/t_typedef_iface_typedef4.v b/test_regress/t/t_typedef_iface_typedef4.v new file mode 100644 index 000000000..5486e57e8 --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef4.v @@ -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 diff --git a/test_regress/t/t_typedef_iface_typedef5.py b/test_regress/t/t_typedef_iface_typedef5.py new file mode 100755 index 000000000..c6e56559a --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef5.py @@ -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() diff --git a/test_regress/t/t_typedef_iface_typedef5.v b/test_regress/t/t_typedef_iface_typedef5.v new file mode 100644 index 000000000..5735c10af --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef5.v @@ -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 diff --git a/test_regress/t/t_typedef_iface_typedef6.py b/test_regress/t/t_typedef_iface_typedef6.py new file mode 100755 index 000000000..c6e56559a --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef6.py @@ -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() diff --git a/test_regress/t/t_typedef_iface_typedef6.v b/test_regress/t/t_typedef_iface_typedef6.v new file mode 100644 index 000000000..db4b90ef7 --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef6.v @@ -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 diff --git a/test_regress/t/t_typedef_iface_typedef7.py b/test_regress/t/t_typedef_iface_typedef7.py new file mode 100755 index 000000000..c6e56559a --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef7.py @@ -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() diff --git a/test_regress/t/t_typedef_iface_typedef7.v b/test_regress/t/t_typedef_iface_typedef7.v new file mode 100644 index 000000000..2842fad0c --- /dev/null +++ b/test_regress/t/t_typedef_iface_typedef7.v @@ -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