diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 859b606d7..a2f8f8fd5 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -852,7 +852,7 @@ class AstClocking final : public AstNode { // @astgen op2 := itemsp : List[AstNode] // @astgen op3 := eventp : Optional[AstVar] std::string m_name; // Clocking block name - const bool m_isDefault; // True if default clocking + bool m_isDefault; // True if default clocking const bool m_isGlobal; // True if global clocking public: @@ -873,6 +873,7 @@ public: bool isDefault() const { return m_isDefault; } bool isGlobal() const { return m_isGlobal; } AstVar* ensureEventp(bool childDType = false); + void makeDefault() { m_isDefault = true; } }; class AstClockingItem final : public AstNode { // Parents: CLOCKING @@ -1230,6 +1231,16 @@ public: ASTGEN_MEMBERS_AstDefParam; bool sameNode(const AstNode*) const override { return true; } }; +class AstDefaultClocking final : public AstNode { + std::string m_name; // Clocking block name + +public: + AstDefaultClocking(FileLine* fl, const std::string& name) + : ASTGEN_SUPER_DefaultClocking(fl) + , m_name{name} {} + ASTGEN_MEMBERS_AstDefaultClocking; + std::string name() const override VL_MT_STABLE { return m_name; } +}; class AstDefaultDisable final : public AstNode { // @astgen op1 := condp : AstNodeExpr diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 933c555d9..210f157f3 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -4139,6 +4139,18 @@ class LinkDotResolveVisitor final : public VNVisitor { } UINFO(8, indent() << "done " << m_ds.ascii() << " " << nodep); } + void visit(AstDefaultClocking* nodep) override { + if (VSymEnt* const foundp = m_curSymp->findIdFallback(nodep->name())) { + if (AstClocking* const clockingp = VN_CAST(foundp->nodep(), Clocking)) { + clockingp->makeDefault(); + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + } else { + nodep->v3error(nodep->prettyNameQ() << " is not a clocking identifier"); + } + } else { + nodep->v3error("Can't find definition of clocking: " << nodep->prettyNameQ()); + } + } void visit(AstSenItem* nodep) override { LINKDOT_VISIT_START(); VL_RESTORER(m_inSens); diff --git a/src/verilog.y b/src/verilog.y index 4c729b893..2a876a6d2 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2776,7 +2776,7 @@ module_or_generate_item_declaration: // ==IEEE: module_or_generate_it modDefaultClocking: // IEEE: part of module_or_generate_item_declaration/checker_or_... yDEFAULT yCLOCKING idAny/*new-clocking_identifier*/ ';' - { $$ = nullptr; BBUNSUP($1, "Unsupported: default clocking identifier"); } + { $$ = new AstDefaultClocking{$2, *$3}; } ; defaultDisable: // IEEE: part of module_/checker_or_generate_item_declaration diff --git a/test_regress/t/t_checker_unsup.out b/test_regress/t/t_checker_unsup.out index 3f8643ee3..6247f857f 100644 --- a/test_regress/t/t_checker_unsup.out +++ b/test_regress/t/t_checker_unsup.out @@ -11,9 +11,6 @@ %Error-UNSUPPORTED: t/t_checker_unsup.v:43:3: Unsupported: checker rand 43 | rand bit randed; | ^~~~ -%Error-UNSUPPORTED: t/t_checker_unsup.v:65:3: Unsupported: default clocking identifier - 65 | default clocking clk; - | ^~~~~~~ %Error-UNSUPPORTED: t/t_checker_unsup.v:68:11: Unsupported: recursive 'checker' 68 | checker ChkChk; | ^~~~~~ diff --git a/test_regress/t/t_clocking_default_bad.out b/test_regress/t/t_clocking_default_bad.out new file mode 100644 index 000000000..99df38988 --- /dev/null +++ b/test_regress/t/t_clocking_default_bad.out @@ -0,0 +1,6 @@ +%Error: t/t_clocking_default_bad.v:13:12: Only one default clocking block allowed per module (IEEE 1800-2023 14.12) + : ... note: In instance 't' + 13 | clocking cb2 @(negedge clk); + | ^~~ + ... 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_clocking_default_bad.py b/test_regress/t/t_clocking_default_bad.py new file mode 100755 index 000000000..c7d9b21a5 --- /dev/null +++ b/test_regress/t/t_clocking_default_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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-FileCopyrightText: 2024 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_clocking_default_bad.v b/test_regress/t/t_clocking_default_bad.v new file mode 100644 index 000000000..876c0f922 --- /dev/null +++ b/test_regress/t/t_clocking_default_bad.v @@ -0,0 +1,18 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Antmicro +// SPDX-License-Identifier: CC0-1.0 + +module t ( + input clk + ); + + clocking cb1 @(posedge clk); + endclocking + clocking cb2 @(negedge clk); + endclocking + + default clocking cb1; + default clocking cb2; +endmodule diff --git a/test_regress/t/t_clocking_default_bad2.out b/test_regress/t/t_clocking_default_bad2.out new file mode 100644 index 000000000..8e2562e24 --- /dev/null +++ b/test_regress/t/t_clocking_default_bad2.out @@ -0,0 +1,8 @@ +%Error: t/t_clocking_default_bad2.v:14:11: Can't find definition of clocking: 'cb_nonexistent' + 14 | default clocking cb_nonexistent; + | ^~~~~~~~ + ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. +%Error: t/t_clocking_default_bad2.v:15:11: 'foo' is not a clocking identifier + 15 | default clocking foo; + | ^~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_clocking_default_bad2.py b/test_regress/t/t_clocking_default_bad2.py new file mode 100755 index 000000000..c7d9b21a5 --- /dev/null +++ b/test_regress/t/t_clocking_default_bad2.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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-FileCopyrightText: 2024 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_clocking_default_bad2.v b/test_regress/t/t_clocking_default_bad2.v new file mode 100644 index 000000000..068c11de6 --- /dev/null +++ b/test_regress/t/t_clocking_default_bad2.v @@ -0,0 +1,16 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Antmicro +// SPDX-License-Identifier: CC0-1.0 + +module t ( + input clk + ); + + initial begin: foo + end + + default clocking cb_nonexistent; + default clocking foo; +endmodule diff --git a/test_regress/t/t_clocking_default_identifier.py b/test_regress/t/t_clocking_default_identifier.py new file mode 100755 index 000000000..c1140f359 --- /dev/null +++ b/test_regress/t/t_clocking_default_identifier.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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-FileCopyrightText: 2024 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=["--timing"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_clocking_default_identifier.v b/test_regress/t/t_clocking_default_identifier.v new file mode 100644 index 000000000..d86c05608 --- /dev/null +++ b/test_regress/t/t_clocking_default_identifier.v @@ -0,0 +1,32 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Antmicro +// SPDX-License-Identifier: CC0-1.0 + +module t ( + input clk + ); + int cyc = 0; + + always @(negedge clk) begin // negedge so there is nothing after $finish + cyc <= cyc + 1; + if (cyc == 12) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + clocking cb @(posedge clk); + endclocking + + default clocking cb; + initial begin + ## 2; + if ($time != 20) $stop; + ## 5; + if ($time != 70) $stop; + ## 3; + if ($time != 100) $stop; + end +endmodule