Internals/Tests: Add `--debug-preproc-passthru` to cleanup some missing dev coverage items

This commit is contained in:
Wilson Snyder 2025-10-11 14:15:04 -04:00
parent 6e8bd3da19
commit 8785086bc8
24 changed files with 139 additions and 19 deletions

View File

@ -1336,6 +1336,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
DECL_OPTION("-debug-leak", OnOff, &m_debugLeak);
DECL_OPTION("-debug-nondeterminism", OnOff, &m_debugNondeterminism);
DECL_OPTION("-debug-partition", OnOff, &m_debugPartition).undocumented();
DECL_OPTION("-debug-preproc-passthru", OnOff, &m_debugPreprocPassthru);
DECL_OPTION("-debug-protect", OnOff, &m_debugProtect).undocumented();
DECL_OPTION("-debug-self-test", OnOff, &m_debugSelfTest).undocumented();
DECL_OPTION("-debug-sigsegv", CbCall, throwSigsegv).undocumented(); // See also --debug-abort

View File

@ -240,6 +240,7 @@ private:
bool m_debugLeak = true; // main switch: --debug-leak
bool m_debugNondeterminism = false; // main switch: --debug-nondeterminism
bool m_debugPartition = false; // main switch: --debug-partition
bool m_debugPreprocPassthru = false; // main switch: --debug-preproc-passthru
bool m_debugProtect = false; // main switch: --debug-protect
bool m_debugSelfTest = false; // main switch: --debug-self-test
bool m_debugStackCheck = false; // main switch: --debug-stack-check
@ -512,6 +513,7 @@ public:
bool debugLeak() const { return m_debugLeak; }
bool debugNondeterminism() const { return m_debugNondeterminism; }
bool debugPartition() const { return m_debugPartition; }
bool debugPreprocPassthru() const VL_MT_SAFE { return m_debugPreprocPassthru; }
bool debugProtect() const VL_MT_SAFE { return m_debugProtect; }
bool debugSelfTest() const { return m_debugSelfTest; }
bool debugStackCheck() const { return m_debugStackCheck; }

View File

@ -195,6 +195,7 @@ public: // Used only by V3PreLex.cpp and V3PreProc.cpp
VL_DO_CLEAR(yy_delete_buffer(m_bufferState), m_bufferState = nullptr);
yylex_destroy();
}
VPreStream* newStream(FileLine* fl, V3PreLex* lexp);
// Called by V3PreLex.l from lexer
VPreStream* curStreamp() { return m_streampStack.top(); } // Can't be empty, "EOF" is on top
@ -219,6 +220,7 @@ public: // Used only by V3PreLex.cpp and V3PreProc.cpp
void pushStateDefValue();
void pushStateExpr();
void pushStateIncFilename();
void pushStatePassthru();
void scanNewFile(FileLine* filelinep);
void scanBytes(const string& str);
void scanBytesBack(const string& str);

View File

@ -75,6 +75,7 @@ static void appendDefValue(const char* t, size_t l) { LEXP->appendDefValue(t, l)
%x ENCBASE64
%x EXPR
%x INCMODE
%x PASSTHRU
%x PRAGMA
%x PRAGMAERR
%x PRAGMAPRT
@ -102,12 +103,15 @@ bom [\357\273\277]
/**************************************************************/
%%
/* Passthru, to support dev-coverage of some main verilog.l rules */
<PASSTHRU>{crnl} { FL_FWDC; linenoInc(); yytext=(char*)"\n"; yyleng=1; return VP_WHITE; }
<PASSTHRU>{word} { yymore(); }
<PASSTHRU>. { FL_FWDC; return VP_TEXT; }
/* Special directives we recognize */
<INITIAL>{bom} { }
<INITIAL,STRIFY>^{ws}*"`line"{ws}+.*{crnl} { FL_FWDC; LEXP->lineDirective(yytext);
return VP_LINE; }
/* Special directives we recognize */
<INITIAL>"`define" { FL_FWDC; return VP_DEFINE; }
<INITIAL>"`else" { FL_FWDC; return VP_ELSE; }
<INITIAL>"`elsif" { FL_FWDC; return VP_ELSIF; }
@ -512,9 +516,20 @@ void V3PreLex::pushStateIncFilename() {
yymore();
}
void V3PreLex::pushStatePassthru() {
yy_push_state(PASSTHRU);
yymore();
}
void V3PreLex::setYYDebug(bool on) {
yy_flex_debug = static_cast<int>(on); }
VPreStream* V3PreLex::newStream(FileLine* fl, V3PreLex* lexp) {
VPreStream* const streamp = new VPreStream{fl, lexp};
if (v3Global.opt.debugPreprocPassthru()) streamp->m_lexp->pushStatePassthru();
return streamp;
}
int V3PreLex::lex() {
V3PreLex::s_currentLexp = this; // Tell parser where to get/put data
// Remember token start location, may be updated by the lexer later
@ -640,7 +655,7 @@ string V3PreLex::endOfStream(bool& againr) {
void V3PreLex::initFirstBuffer(FileLine* filelinep) {
// Called from constructor to make first buffer
// yy_create_buffer also sets yy_fill_buffer=1 so reads from YY_INPUT
VPreStream* const streamp = new VPreStream{filelinep, this};
VPreStream* const streamp = newStream(filelinep, this);
streamp->m_eof = true;
m_streampStack.push(streamp);
//
@ -656,7 +671,7 @@ void V3PreLex::scanNewFile(FileLine* filelinep) {
yyerrorf("Recursive `define or other nested inclusion");
curStreamp()->m_eof = true; // Fake it to stop recursion
} else {
VPreStream* const streamp = new VPreStream{filelinep, this};
VPreStream* const streamp = newStream(filelinep, this);
m_tokFilelinep = curFilelinep();
streamp->m_file = true;
scanSwitchStream(streamp);
@ -675,7 +690,7 @@ void V3PreLex::scanBytes(const string& str) {
yyerrorf("Recursive `define or other nested inclusion");
curStreamp()->m_eof = true; // Fake it to stop recursion
} else {
VPreStream* const streamp = new VPreStream{curFilelinep(), this};
VPreStream* const streamp = newStream(curFilelinep(), this);
streamp->m_buffers.push_front(str);
scanSwitchStream(streamp);
}

View File

@ -297,7 +297,7 @@ public:
// Creation
V3PreProc* V3PreProc::createPreProc(FileLine* fl) {
V3PreProcImp* preprocp = new V3PreProcImp;
V3PreProcImp* const preprocp = new V3PreProcImp;
preprocp->configure(fl);
return preprocp;
}

View File

@ -1045,14 +1045,14 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
/************************************************************************/
/* Tables */
<TABLE>[rRfFpPnN\*] { FL; yylval.strp = PARSEP->newString(yytext, yyleng); return yaTABLE_FIELD; } /* edge_symbol */
<TABLE>[01xX\?bB\-] { FL; yylval.strp = PARSEP->newString(yytext, yyleng); return yaTABLE_FIELD; } /* level_symbol, next_state */
<TABLE>":" { FL; return yaTABLE_LRSEP; } /* LHS and RHS separator for table line. */
<TABLE>[rRfFpPnN\*] { FL; yylval.strp = PARSEP->newString(yytext, yyleng); return yaTABLE_FIELD; } /* edge_symbol */
<TABLE>[01xX\?bB\-] { FL; yylval.strp = PARSEP->newString(yytext, yyleng); return yaTABLE_FIELD; } /* level_symbol, next_state */
<TABLE>":" { FL; return yaTABLE_LRSEP; } /* LHS and RHS separator for table line. */
<TABLE>";" { FL; return yaTABLE_LINEEND; }
<TABLE>[\(\)] { FL; return yytext[0]; }
<TABLE>{ws}|(\\){0,1}{crnl} { FL_FWD; FL_BRK; }
<TABLE>"`line"{ws}+[^\n\r]*{crnl} { FL_FWD; PARSEP->lexPpline(yytext); FL_BRK; }
<TABLE>"//"[^\n]* { FL_FWD; FL_BRK; } /* throw away single line comments */
<TABLE>"//"[^\n]* { FL_FWD; FL_BRK; } /* Throw away single line comments */
<TABLE>"endtable" { FL; yy_pop_state(); return yENDTABLE; }
<TABLE><<EOF>> { FL; yylval.fl->v3error("EOF in 'table'");
yyleng = 0; yy_pop_state(); FL_BRK; yyterminate(); }
@ -1176,14 +1176,14 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
<V95,V01NC,V01C,V05,VA5,S05,S09,S12,S17,S23,SAX,VLT>{
"`"[a-zA-Z_0-9]+ { FL; V3ParseImp::lexErrorPreprocDirective(yylval.fl, yytext); FL_BRK; }
"//"[^\n]* { FL_FWD; FL_BRK; } /* throw away single line comments */
. { FL; return yytext[0]; } /* return single char ops. */
. { FL; return yytext[0]; } /* return single char ops. */
}
/* Catch all - absolutely last */
<*>.|\n { FL; yylval.fl->v3error( // LCOV_EXCL_LINE
"Missing verilog.l rule: Default rule invoked in state "
<< YY_START << " '" << yytext << "'");
FL_BRK; }
FL_BRK; } /* LCOV_EXCL_LINE */
%%
// Avoid code here as cl format misindents
// For implementation functions see V3ParseImp.cpp

View File

@ -23,7 +23,6 @@ for s in [
'Assigned pin is neither input nor output', # Instead earlier error
'Define missing argument \'', # Instead get Define passed too many arguments
'Define or directive not defined: `', # Instead V3ParseImp will warn
'EOF in unterminated string', # Instead get normal unterminated
'Enum ranges must be integral, per spec', # Hard to hit
'Expecting define formal arguments. Found: ', # Instead define syntax error
'Syntax error parsing real: \'', # Instead can't lex the number
@ -61,13 +60,11 @@ for s in [
'Slices of arrays in assignments have different unpacked dimensions, ',
'String of ',
'Symbol matching ',
'Type cannot be selected from',
'Unexpected connection to arrayed port',
'Unsized numbers/parameters not allowed in streams.',
'Unsupported RHS tristate construct: ',
'Unsupported or syntax error: Unsized range in instance or other declaration',
'Unsupported pullup/down (weak driver) construct.',
'Unsupported tristate construct (not in propagation graph): ',
'Unsupported tristate port expression: ',
'Unsupported: $bits for queue',
'Unsupported: &&& expression',
@ -81,7 +78,6 @@ for s in [
'Unsupported: Per-bit array instantiations ',
'Unsupported: Public functions with >64 bit outputs; ',
'Unsupported: Replication to form ',
'Unsupported: Shifting of by over 32-bit number isn\'t supported.',
'Unsupported: Size-changing cast on non-basic data type',
'Unsupported: Slice of non-constant bounds',
'Unsupported: Unclocked assertion',
@ -92,7 +88,6 @@ for s in [
'Unsupported: \'{} .* patterns',
'Unsupported: assertion items in clocking blocks',
'Unsupported: don\'t know how to deal with ',
'Unsupported: eventually[] (in property expression)',
'Unsupported: extern forkjoin',
'Unsupported: extern task',
'Unsupported: modport export',

View File

@ -12,3 +12,5 @@ public_flat_rw -module "sub" -var "in_a"
public_flat_rw -module "sub" -var "in_b" @(posedge t.monclk)
public_flat_rw -module "sub" -var "fr_a"
public_flat_rw -module "sub" -var "fr_b" @(posedge t.monclk)
// Cover other edge declarations
public_flat_rw -module "sub" -var "fr_chk" @(posedge t.monclk or negedge t.monclk or edge t.monclk)

View File

@ -1,4 +1,4 @@
%Error: t/t_preproc_eof5_bad.v:7:1: EOF in (*
%Error: t/t_parse_eof_attr_bad.v:7:1: EOF in (*
7 | (* attr
| ^
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.

View File

@ -0,0 +1,5 @@
%Error: t/t_parse_eof_qqq_bad.v:7:1: EOF in unterminated """ string
7 | """
| ^
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -0,0 +1,18 @@
#!/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(verilator_flags2=['--debug-preproc-passthru', '--no-std'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,7 @@
%Error: t/t_parse_eof_str_bad.v:9:10: syntax error, unexpected IDENTIFIER, expecting ';'
9 | `line 9 "t/t_parse_eof_str_bad.v" 0
| ^
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_parse_eof_str_bad.v:11:33: Unterminated string
%Error: t/t_parse_eof_str_bad.v:11:1: EOF in unterminated string
%Error: Exiting due to

View File

@ -0,0 +1,18 @@
#!/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(verilator_flags2=['--debug-preproc-passthru', '--no-std'],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2019 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
localparam string STR = "str

View File

@ -1,3 +1,3 @@
%Error: t/t_preproc_eof6_bad.v:10:1: EOF in unterminated """ string
%Error: t/t_preproc_eof_qqq_bad.v:10:1: EOF in unterminated """ string
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: Exiting due to

View File

@ -0,0 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2019 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
"""str

View File

@ -11,6 +11,9 @@ import vltest_bootstrap
test.scenarios('vlt')
if test.have_dev_gcov:
test.skip("Test suite intended for full dev coverage without needing this test")
test.compile(v_flags2=["--timing", "+incdir+t/uvm", "t/t_uvm_todo.vlt", "-j 0"],
make_flags=['-k'],
verilator_make_gmake=False)

16
test_regress/t/t_vlt_legacy.py Executable file
View File

@ -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('vlt')
test.lint(verilator_flags2=[test.t_dir + "/" + test.name + ".vlt"])
test.passes()

View File

@ -0,0 +1,11 @@
// 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
module t (
input clk /*verilator clock_enable*/
);
initial $finish;
endmodule

View File

@ -0,0 +1,11 @@
// 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
`verilator_config
clock_enable --module "t" --var "clk"
clocker --module "t" --var "clk"
no_clocker --module "t" --var "clk"