diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index 4cb67cfa2..5ccec4121 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -1171,11 +1171,13 @@ class AstRefDType final : public AstNodeDType { // // Pre-Width must reference the Typeref, not what it points to, as some child // types like AstBracketArrayType will disappear and can't lose the handle + // // @astgen ptr := m_typedefp : Optional[AstTypedef] // Referenced type // Post-width typedefs are removed and point to type directly // @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) @@ -1192,6 +1194,11 @@ 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 { @@ -1206,6 +1213,7 @@ 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 195fc31b7..e66684ccd 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -2318,10 +2318,15 @@ 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 { dumpJsonGen(str); } +void AstRefDType::dumpJson(std::ostream& str) const { + if (!ifacePortName().empty()) dumpJsonStr(str, "ifcPortName", ifacePortName()); + dumpJsonGen(str); +} + void AstRefDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); str << "ref"; diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 8a38c03a0..255080a32 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -4961,6 +4961,9 @@ 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 { diff --git a/src/verilog.y b/src/verilog.y index 64e57038d..19b81dfed 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2516,8 +2516,9 @@ type_declaration: // ==IEEE: type_declaration AstNodeDType* const dtp = GRAMMARP->createArray(refp, $4, true); $$ = GRAMMARP->createTypedef($5, *$5, $7, dtp, $6); } // // - | yTYPEDEF idAny/*interface*/ '.' idAny/*type*/ idAny/*type*/ dtypeAttrListE ';' - { $$ = nullptr; BBUNSUP($1, "Unsupported: SystemVerilog 2005 typedef in this context"); DEL($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 diff --git a/test_regress/t/t_interface_typedef.out b/test_regress/t/t_interface_typedef.out index ab677162e..fe9d6e06f 100644 --- a/test_regress/t/t_interface_typedef.out +++ b/test_regress/t/t_interface_typedef.out @@ -1,5 +1,5 @@ -%Error-UNSUPPORTED: t/t_interface_typedef.v:46:4: Unsupported: SystemVerilog 2005 typedef in this context - 46 | typedef ifc_if.struct_t struct_t; - | ^~~~~~~ - ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: t/t_interface_typedef.v:49:11: Unsupported: SystemVerilog 2005 interface typedef + 49 | typedef ifc_if.struct_t struct_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.py b/test_regress/t/t_interface_typedef.py index 966dc53da..da7d64435 100755 --- a/test_regress/t/t_interface_typedef.py +++ b/test_regress/t/t_interface_typedef.py @@ -9,9 +9,11 @@ import vltest_bootstrap -test.scenarios('simulator') +test.scenarios('simulator_st') -test.compile(fails=test.vlt_all, expect_filename=test.golden_filename) +test.compile(verilator_flags2=['--binary'], + fails=test.vlt_all, + expect_filename=test.golden_filename) if not test.vlt_all: test.execute() diff --git a/test_regress/t/t_interface_typedef.v b/test_regress/t/t_interface_typedef.v index c3491894d..2085e38bc 100644 --- a/test_regress/t/t_interface_typedef.v +++ b/test_regress/t/t_interface_typedef.v @@ -4,54 +4,58 @@ // any use, without warranty, 2021 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 +// verilog_format: off `define stop $stop -`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0) +`define checkh(gotv, expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0) +// verilog_format: on -interface ifc - #( +interface ifc #( parameter int unsigned WIDTH - ) (); - typedef struct { - logic [WIDTH-1:0] data; - } struct_t; +) (); + typedef struct {logic [WIDTH-1:0] data;} struct_t; endinterface -module t (/*AUTOARG*/ - // Inputs - clk - ); - input clk; +module t ( /*AUTOARG*/ + // Inputs + clk +); + input clk; - ifc #(10) i_ifc10(); - ifc #(20) i_ifc20(); + ifc #(10) i_ifc10 (); + ifc #(20) i_ifc20 (); - sub #(10) u_sub10 (.clk, .ifc_if(i_ifc10)); - sub #(20) u_sub20 (.clk, .ifc_if(i_ifc20)); + sub #(10) u_sub10 ( + .clk, + .ifc_if(i_ifc10) + ); + sub #(20) u_sub20 ( + .clk, + .ifc_if(i_ifc20) + ); - integer cyc = 1; - always @ (posedge clk) begin - cyc <= cyc + 1; - if (cyc==20) begin - $write("*-* All Finished *-*\n"); - $finish; - end - end + initial begin + #100; + $write("*-* All Finished *-*\n"); + $finish; + end endmodule module sub #( - parameter int EXP_WIDTH) - ( + parameter int EXP_WIDTH +) ( input logic clk, - ifc ifc_if); - typedef ifc_if.struct_t struct_t; + ifc ifc_if +); + typedef ifc_if.struct_t struct_t; - wire [EXP_WIDTH-1:0] expval = '1; + wire [EXP_WIDTH-1:0] expval = '1; - initial begin - struct_t substruct; - substruct.data = '1; - `checkh($bits(struct_t), EXP_WIDTH); - `checkh(substruct.data, expval); - end + initial begin + struct_t substruct; + #10; + substruct.data = '1; + `checkh($bits(struct_t), EXP_WIDTH); + `checkh(substruct.data, expval); + end endmodule diff --git a/test_regress/t/t_interface_typedef2.out b/test_regress/t/t_interface_typedef2.out new file mode 100644 index 000000000..7f8fee0bd --- /dev/null +++ b/test_regress/t/t_interface_typedef2.out @@ -0,0 +1,11 @@ +%Error: t/t_interface_typedef2.v:37:11: Unsupported: SystemVerilog 2005 interface typedef + 37 | typedef p1.stage_t stage1_t; + | ^~ + ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. +%Error: t/t_interface_typedef2.v:40:11: Unsupported: SystemVerilog 2005 interface typedef + 40 | typedef p2.stage_t stage2_t; + | ^~ +%Error: t/t_interface_typedef2.v:25:11: Unsupported: SystemVerilog 2005 interface typedef + 25 | typedef p1.stage_t stage_t; + | ^~ +%Error: Exiting due to diff --git a/test_regress/t/t_interface_typedef2.py b/test_regress/t/t_interface_typedef2.py new file mode 100755 index 000000000..da7d64435 --- /dev/null +++ b/test_regress/t/t_interface_typedef2.py @@ -0,0 +1,21 @@ +#!/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('simulator_st') + +test.compile(verilator_flags2=['--binary'], + fails=test.vlt_all, + expect_filename=test.golden_filename) + +if not test.vlt_all: + test.execute() + +test.passes() diff --git a/test_regress/t/t_interface_typedef2.v b/test_regress/t/t_interface_typedef2.v new file mode 100644 index 000000000..b54aa9dbc --- /dev/null +++ b/test_regress/t/t_interface_typedef2.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 + +interface common_intf #( + int ADDR_W, + DATA_W +); + typedef struct packed { + + logic [ADDR_W-1:0] cntr_idx; + logic [DATA_W-1:0] cntr_val; + + } stage_t; + + stage_t bus; + +endinterface + +module mod1 ( + common_intf p1 +); + typedef p1.stage_t stage_t; // "imports" type into module + stage_t local_bus; + + initial begin + $display("%m mod1: idx bits %0d, val bits %0d", $bits(p1.bus.cntr_idx), $bits(p1.bus.cntr_val)); + end +endmodule + +module mod2 ( + common_intf p1, + p2 +); + typedef p1.stage_t stage1_t; // "imports" type into module + stage1_t local_bus1; + + typedef p2.stage_t stage2_t; // "imports" type into module + stage2_t local_bus2; + + initial begin + $display("%m-1 mod2: idx bits %0d, val bits %0d", $bits(p1.bus.cntr_idx), $bits(p1.bus.cntr_val)); + $display("%m-2 mod2: idx bits %0d, val bits %0d", $bits(p2.bus.cntr_idx), $bits(p2.bus.cntr_val)); + $display("%m mod2: params p1 ADDR_W %0d DATA_W %0d", p1.ADDR_W, p1.DATA_W); + $display("%m mod2: params p2 ADDR_W %0d DATA_W %0d", p2.ADDR_W, p2.DATA_W); + end + +endmodule + +module t; + common_intf #(8, 16) i1_2 (); // connects m1 to m2 + common_intf #(4, 32) i2_3 (); // connects m2 to m3 + mod1 m1 (i1_2); + mod2 m2 ( + i1_2, + i2_3 + ); + mod1 m3 (i2_3); + initial begin + #10; + $finish; + end +endmodule diff --git a/test_regress/t/t_interface_typedef3.out b/test_regress/t/t_interface_typedef3.out new file mode 100644 index 000000000..81f7b6d6c --- /dev/null +++ b/test_regress/t/t_interface_typedef3.out @@ -0,0 +1,5 @@ +%Error: t/t_interface_typedef3.v:22:11: Unsupported: SystemVerilog 2005 interface typedef + 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_typedef3.py b/test_regress/t/t_interface_typedef3.py new file mode 100755 index 000000000..da7d64435 --- /dev/null +++ b/test_regress/t/t_interface_typedef3.py @@ -0,0 +1,21 @@ +#!/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('simulator_st') + +test.compile(verilator_flags2=['--binary'], + fails=test.vlt_all, + expect_filename=test.golden_filename) + +if not test.vlt_all: + test.execute() + +test.passes() diff --git a/test_regress/t/t_interface_typedef3.v b/test_regress/t/t_interface_typedef3.v new file mode 100644 index 000000000..f77507742 --- /dev/null +++ b/test_regress/t/t_interface_typedef3.v @@ -0,0 +1,32 @@ +// 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 + +// verilog_format: off +`define stop $stop +`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0); +// verilog_format: on + +interface ifc; + typedef logic [3:0] choice_t; + choice_t q; + localparam int ONE = 1; + modport mp(input q); +endinterface + +module sub ( + interface.mp iface_mp +); + typedef iface_mp.choice_t tdef_t; + tdef_t P; + initial begin + `checkd($bits(tdef_t), 4); + end +endmodule + +module t; + ifc u_ifc (); + sub u_sub (u_ifc.mp); +endmodule diff --git a/test_regress/t/t_interface_typedef_bad.out b/test_regress/t/t_interface_typedef_bad.out new file mode 100644 index 000000000..1c91f464c --- /dev/null +++ b/test_regress/t/t_interface_typedef_bad.out @@ -0,0 +1,11 @@ +%Error: t/t_interface_typedef_bad.v:15:11: Unsupported: SystemVerilog 2005 interface typedef + 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 + 16 | typedef i.not_found_t choice2_t; + | ^ +%Error: t/t_interface_typedef_bad.v:17:11: Unsupported: SystemVerilog 2005 interface typedef + 17 | typedef not_ifc.x_t choice3_t; + | ^~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_interface_typedef_bad.py b/test_regress/t/t_interface_typedef_bad.py new file mode 100755 index 000000000..30c3d4f77 --- /dev/null +++ b/test_regress/t/t_interface_typedef_bad.py @@ -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('linter') + +test.lint(fails=test.vlt_all, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_interface_typedef_bad.v b/test_regress/t/t_interface_typedef_bad.v new file mode 100644 index 000000000..e71a0bcc3 --- /dev/null +++ b/test_regress/t/t_interface_typedef_bad.v @@ -0,0 +1,23 @@ +// 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 ifc; + integer i; +endinterface + +module sub ( + interface i +); + logic not_ifc; + typedef not_found.choice_t choice1_t; // <--- Error: not found interface port + typedef i.not_found_t choice2_t; // <--- Error: not found typedef + typedef not_ifc.x_t choice3_t; // <--- Error: sub not interface reference +endmodule + +module t; + ifc u_ifc (); + sub u_sub (u_ifc); +endmodule