From 7d43a935bd4404d04e56a87350d152197ba942bb Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 18 Jul 2025 19:32:34 -0400 Subject: [PATCH] Add SPECIFYIGN warning for specify constructs that were previously silently ignored. --- Changes | 1 + docs/guide/warnings.rst | 16 +++++++++-- src/V3Error.h | 13 ++++----- src/V3Options.cpp | 2 ++ src/verilog.l | 1 + src/verilog.y | 30 ++++++++++++++++----- test_regress/t/t_gate_basic.py | 2 +- test_regress/t/t_gate_basic_specify_bad.out | 22 +++++++++++++++ test_regress/t/t_gate_basic_specify_bad.py | 17 ++++++++++++ test_regress/t/t_gate_basic_timing.py | 3 ++- test_regress/t/t_gate_delay_unsup.py | 4 ++- test_regress/t/t_sdf_annotate_unsup.out | 15 +++++++++++ test_regress/t/t_sdf_annotate_unsup.py | 16 +++++++++++ test_regress/t/t_sdf_annotate_unsup.v | 20 ++++++++++++++ 14 files changed, 145 insertions(+), 17 deletions(-) create mode 100644 test_regress/t/t_gate_basic_specify_bad.out create mode 100755 test_regress/t/t_gate_basic_specify_bad.py create mode 100644 test_regress/t/t_sdf_annotate_unsup.out create mode 100755 test_regress/t/t_sdf_annotate_unsup.py create mode 100644 test_regress/t/t_sdf_annotate_unsup.v diff --git a/Changes b/Changes index 12d4e47f5..2d506b97f 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,7 @@ Verilator 5.039 devel * Add ENUMITEMWIDTH error, and apply to X-extended and ranged values. * Add NOEFFECT warning, replacing previous `foreach` error. +* Add SPECIFYIGN warning for specify constructs that were previously silently ignored. * Add enum base type checking per IEEE. * Support member-level triggers for virtual interfaces (#5166) (#6148). [Yilou Wang] * Support disabling a fork in additional contexts (#5432 partial) (#6174) (#6183). [Ryszard Rozak, Antmicro Ltd.] diff --git a/docs/guide/warnings.rst b/docs/guide/warnings.rst index a7143fe3b..9e6d534be 100644 --- a/docs/guide/warnings.rst +++ b/docs/guide/warnings.rst @@ -458,7 +458,7 @@ List Of Warnings Warns that Verilator does not support certain forms of :code:`constraint`, :code:`constraint_mode`, or :code:`rand_mode`, and - the construct was are ignored. + the construct was ignored. Ignoring this warning may make Verilator randomize() simulations differ from other simulators. @@ -486,7 +486,7 @@ List Of Warnings Warns that Verilator does not support certain forms of :code:`covergroup`, :code:`coverpoint`, and coverage options, and the - construct was are ignored. + construct was ignored. Disabling the :option:`UNSUPPORTED` error also disables this warning. @@ -1779,6 +1779,18 @@ List Of Warnings simulators. +.. option:: SPECIFYIGN + + Warns that Verilator does not support certain constructs in + :code:`specify` blocks, nor :code:`$sdf_annotate`, and the construct was + ignored. + + Disabling the :option:`UNSUPPORTED` error also disables this warning. + + Ignoring this warning may make Verilator ignore lint checking on the + construct, and get different results from other simulators. + + .. option:: SPLITVAR Warns that a variable with a :option:`/*verilator&32;split_var*/` diff --git a/src/V3Error.h b/src/V3Error.h index b8ca71866..6706e4891 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -146,6 +146,7 @@ public: SELRANGE, // Selection index out of range SHORTREAL, // Shortreal not supported SIDEEFFECT, // Sideeffect ignored + SPECIFYIGN, // Specify construct ignored SPLITVAR, // Cannot split the variable STATICVAR, // Static variable declared in a loop with a declaration assignment STMTDLY, // Delayed statement @@ -212,12 +213,12 @@ public: "NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD", "NULLPORT", "PINCONNECTEMPTY", "PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PREPROCZERO", "PROCASSINIT", "PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED", "RANDC", "REALCVT", "REDEFMACRO", - "RISEFALLDLY", "SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPLITVAR", "STATICVAR", - "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET", "TICKCOUNT", "TIMESCALEMOD", "UNDRIVEN", - "UNOPT", "UNOPTFLAT", "UNOPTTHREADS", "UNPACKED", "UNSIGNED", "UNUSEDGENVAR", - "UNUSEDLOOP", "UNUSEDPARAM", "UNUSEDSIGNAL", "USERERROR", "USERFATAL", "USERINFO", - "USERWARN", "VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT", "WIDTHEXPAND", - "WIDTHTRUNC", "WIDTHXZEXPAND", "ZERODLY", "ZEROREPL", " MAX"}; + "RISEFALLDLY", "SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPECIFYIGN", "SPLITVAR", + "STATICVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET", "TICKCOUNT", "TIMESCALEMOD", + "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS", "UNPACKED", "UNSIGNED", + "UNUSEDGENVAR", "UNUSEDLOOP", "UNUSEDPARAM", "UNUSEDSIGNAL", "USERERROR", "USERFATAL", + "USERINFO", "USERWARN", "VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT", + "WIDTHEXPAND", "WIDTHTRUNC", "WIDTHXZEXPAND", "ZERODLY", "ZEROREPL", " MAX"}; return names[m_e]; } // Warnings that default to off diff --git a/src/V3Options.cpp b/src/V3Options.cpp index c4643c115..1b64307ce 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1803,8 +1803,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, DECL_OPTION("-Wwarn-UNSUPPORTED", CbCall, []() { FileLine::globalWarnOff(V3ErrorCode::E_UNSUPPORTED, false); FileLine::globalWarnOff(V3ErrorCode::COVERIGN, false); + FileLine::globalWarnOff(V3ErrorCode::SPECIFYIGN, false); V3Error::pretendError(V3ErrorCode::E_UNSUPPORTED, false); V3Error::pretendError(V3ErrorCode::COVERIGN, false); + V3Error::pretendError(V3ErrorCode::SPECIFYIGN, false); }); DECL_OPTION("-Wwarn-WIDTH", CbCall, []() { FileLine::globalWarnOff(V3ErrorCode::WIDTH, false); diff --git a/src/verilog.l b/src/verilog.l index 754368e1c..dc1e3a323 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -270,6 +270,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$rewind" { FL; return yD_REWIND; } "$rtoi" { FL; return yD_RTOI; } "$sampled" { FL; return yD_SAMPLED; } + "$sdf_annotate" { FL; return yD_SDF_ANNOTATE; } "$setup" { FL; return yaTIMINGSPEC; } "$setuphold" { FL; return yD_SETUPHOLD; } "$sformat" { FL; return yD_SFORMAT; } diff --git a/src/verilog.y b/src/verilog.y index b25b207f7..0b57eeab1 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -98,6 +98,7 @@ public: bool m_tracingParse = true; // Tracing disable for parser bool m_inImplements = false; // Is inside class implements list bool m_insideProperty = false; // Is inside property declaration + bool m_specifyignWarned = false; // Issued a SPECIFYIGN warning bool m_typedPropertyPort = false; // Typed property port occurred on port lists bool m_modportImpExpActive = false; // Standalone ID is a tf_identifier instead of port_identifier @@ -926,6 +927,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yD_ROSE_GCLK "$rose_gclk" %token yD_RTOI "$rtoi" %token yD_SAMPLED "$sampled" +%token yD_SDF_ANNOTATE "$sdf_annotate" %token yD_SETUPHOLD "$setuphold" %token yD_SFORMAT "$sformat" %token yD_SFORMATF "$sformatf" @@ -4284,6 +4286,7 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_DUMPON '(' expr ')' { $$ = new AstDumpCtl{$1, VDumpCtlType::ON}; DEL($3); } // | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? nullptr : new AstUCStmt{$1, $3}); } + | yD_SDF_ANNOTATE '(' exprEListE ')' { $$ = nullptr; $1->v3warn(SPECIFYIGN, "Ignoring unsupported: $sdf_annotate"); } | yD_STACKTRACE parenE { $$ = new AstStackTraceT{$1}; } | yD_SYSTEM '(' expr ')' { $$ = new AstSystemT{$1, $3}; } // @@ -5353,6 +5356,11 @@ exprList: | exprList ',' expr { $$ = $1->addNext($3); } ; +exprEListE: // expression list with empty commas allowed + exprE { $$ = $1; } + | exprEListE ',' exprE { $$ = addNextNull($1, $3); } + ; + exprDispList: // exprList for within $display expr { $$ = $1; } | exprDispList ',' expr { $$ = $1->addNext($3); } @@ -5825,8 +5833,12 @@ tablelVal: // Specify specify_block: // ==IEEE: specify_block - ySPECIFY specify_itemList yENDSPECIFY { $$ = $2; } - | ySPECIFY yENDSPECIFY { $$ = nullptr; } + specifyFront specify_itemList yENDSPECIFY { $$ = $2; } + | specifyFront yENDSPECIFY { $$ = nullptr; } + ; + +specifyFront: // IEEE: specify_block front + ySPECIFY { GRAMMARP->m_specifyignWarned = false; } ; specify_itemList: // IEEE: { specify_item } @@ -5837,7 +5849,13 @@ specify_itemList: // IEEE: { specify_item } specify_item: // ==IEEE: specify_item specparam_declaration { $$ = $1; } | system_timing_check { $$ = $1; } - | junkToSemiList ';' { $$ = nullptr; } + | junkToSemiList ';' + { $$ = nullptr; + if (!GRAMMARP->m_specifyignWarned) { + GRAMMARP->m_specifyignWarned = true; + $1->v3warn(SPECIFYIGN, "Ignoring unsupported: specify block construct"); + } + } ; specparam_declaration: // ==IEEE: specparam_declaration @@ -5926,9 +5944,9 @@ idAnyE: | idAny { $$ = $1; } ; -junkToSemiList: - junkToSemi { } /* ignored */ - | junkToSemiList junkToSemi { } /* ignored */ +junkToSemiList: + junkToSemi { $$ = CRELINE(); } + | junkToSemiList junkToSemi { $$ = CRELINE(); } ; junkToSemi: diff --git a/test_regress/t/t_gate_basic.py b/test_regress/t/t_gate_basic.py index e5667d0d0..c98cbe4f8 100755 --- a/test_regress/t/t_gate_basic.py +++ b/test_regress/t/t_gate_basic.py @@ -11,7 +11,7 @@ import vltest_bootstrap test.scenarios('simulator') -test.compile(verilator_flags2=["--no-timing"]) +test.compile(verilator_flags2=["--no-timing", "-Wno-SPECIFYIGN"]) test.execute() diff --git a/test_regress/t/t_gate_basic_specify_bad.out b/test_regress/t/t_gate_basic_specify_bad.out new file mode 100644 index 000000000..8b041a215 --- /dev/null +++ b/test_regress/t/t_gate_basic_specify_bad.out @@ -0,0 +1,22 @@ +%Warning-SPECIFYIGN: t/t_gate_basic.v:50:27: Ignoring unsupported: specify block construct + 50 | (nt0 *> nt0) = (0, 0); + | ^ + ... For warning description see https://verilator.org/warn/SPECIFYIGN?v=latest + ... Use "/* verilator lint_off SPECIFYIGN */" and lint_on around source to disable this message. +%Warning-SPECIFYIGN: t/t_gate_basic.v:60:32: Ignoring unsupported: specify block construct + 60 | (A1 *> Q) = (a$A1$Y, a$A1$Y); + | ^ +%Error-NEEDTIMINGOPT: t/t_gate_basic.v:24:10: Use --timing or --no-timing to specify how timing controls should be handled + : ... note: In instance 't' + 24 | not #(0.108) NT0 (nt0, a[0]); + | ^ + ... For error description see https://verilator.org/warn/NEEDTIMINGOPT?v=latest +%Error-NEEDTIMINGOPT: t/t_gate_basic.v:25:10: Use --timing or --no-timing to specify how timing controls should be handled + : ... note: In instance 't' + 25 | and #1 AN0 (an0, a[0], b[0]); + | ^ +%Error-NEEDTIMINGOPT: t/t_gate_basic.v:26:10: Use --timing or --no-timing to specify how timing controls should be handled + : ... note: In instance 't' + 26 | nand #(2,3) ND0 (nd0, a[0], b[0], b[1]); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_gate_basic_specify_bad.py b/test_regress/t/t_gate_basic_specify_bad.py new file mode 100755 index 000000000..07db30dae --- /dev/null +++ b/test_regress/t/t_gate_basic_specify_bad.py @@ -0,0 +1,17 @@ +#!/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.top_filename = 't/t_gate_basic.v' + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_gate_basic_timing.py b/test_regress/t/t_gate_basic_timing.py index cfcba0b42..12c73db41 100755 --- a/test_regress/t/t_gate_basic_timing.py +++ b/test_regress/t/t_gate_basic_timing.py @@ -13,7 +13,8 @@ test.scenarios('simulator') test.top_filename = "t/t_gate_basic.v" test.main_time_multiplier = 10e-7 / 10e-9 -test.compile(timing_loop=True, verilator_flags2=["--timing --timescale 10ns/1ns -Wno-RISEFALLDLY"]) +test.compile(timing_loop=True, + verilator_flags2=["--timing --timescale 10ns/1ns -Wno-RISEFALLDLY -Wno-SPECIFYIGN"]) test.execute() diff --git a/test_regress/t/t_gate_delay_unsup.py b/test_regress/t/t_gate_delay_unsup.py index 3e0229f9a..9591d0ead 100755 --- a/test_regress/t/t_gate_delay_unsup.py +++ b/test_regress/t/t_gate_delay_unsup.py @@ -12,7 +12,9 @@ import vltest_bootstrap test.scenarios('linter') test.top_filename = "t/t_gate_basic.v" -test.lint(verilator_flags2=["--lint-only -Wall -Wno-DECLFILENAME -Wno-UNUSED --timing"], +test.lint(verilator_flags2=[ + "--lint-only --timing -Wall", "-Wno-DECLFILENAME -Wno-SPECIFYIGN -Wno-UNUSED" +], fails=True, expect_filename=test.golden_filename) diff --git a/test_regress/t/t_sdf_annotate_unsup.out b/test_regress/t/t_sdf_annotate_unsup.out new file mode 100644 index 000000000..016202286 --- /dev/null +++ b/test_regress/t/t_sdf_annotate_unsup.out @@ -0,0 +1,15 @@ +%Warning-SPECIFYIGN: t/t_sdf_annotate_unsup.v:10:5: Ignoring unsupported: $sdf_annotate + 10 | $sdf_annotate("file.sdf"); + | ^~~~~~~~~~~~~ + ... For warning description see https://verilator.org/warn/SPECIFYIGN?v=latest + ... Use "/* verilator lint_off SPECIFYIGN */" and lint_on around source to disable this message. +%Warning-SPECIFYIGN: t/t_sdf_annotate_unsup.v:11:5: Ignoring unsupported: $sdf_annotate + 11 | $sdf_annotate("file.sdf",); + | ^~~~~~~~~~~~~ +%Warning-SPECIFYIGN: t/t_sdf_annotate_unsup.v:12:5: Ignoring unsupported: $sdf_annotate + 12 | $sdf_annotate("file.sdf", t); + | ^~~~~~~~~~~~~ +%Warning-SPECIFYIGN: t/t_sdf_annotate_unsup.v:14:5: Ignoring unsupported: $sdf_annotate + 14 | $sdf_annotate("file.sdf", t, "config_file", "log_file", "mtm_spec", "scale_factors", + | ^~~~~~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_sdf_annotate_unsup.py b/test_regress/t/t_sdf_annotate_unsup.py new file mode 100755 index 000000000..272fc1280 --- /dev/null +++ b/test_regress/t/t_sdf_annotate_unsup.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_sdf_annotate_unsup.v b/test_regress/t/t_sdf_annotate_unsup.v new file mode 100644 index 000000000..dcad1c56c --- /dev/null +++ b/test_regress/t/t_sdf_annotate_unsup.v @@ -0,0 +1,20 @@ +// DESCRIPTION: Verilator: Verilog Test module for SystemVerilog 'alias' +// +// 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 + +module t; + + initial begin + $sdf_annotate("file.sdf"); + $sdf_annotate("file.sdf",); + $sdf_annotate("file.sdf", t); + // TArguments are all optional, so test more exhaustively + $sdf_annotate("file.sdf", t, "config_file", "log_file", "mtm_spec", "scale_factors", + "scale_type"); + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule