Add `--preproc-defines`.

This commit is contained in:
Wilson Snyder 2025-11-01 23:27:43 -04:00
parent 1d69c18e33
commit c801237ce8
12 changed files with 1608 additions and 2 deletions

View File

@ -27,6 +27,7 @@ Verilator 5.041 devel
* Add NORETURN warning on functions without return values (#6534). [Alex Solomatnikov] * Add NORETURN warning on functions without return values (#6534). [Alex Solomatnikov]
* Add `--aslr` and `--no-aslr` options. * Add `--aslr` and `--no-aslr` options.
* Add `$cpure` (#6580). [Igor Zaworski, Antmicro Ltd.] * Add `$cpure` (#6580). [Igor Zaworski, Antmicro Ltd.]
* Add `--preproc-defines`.
* Deprecate sensitivity list on public_flat_rw attributes (#6443). [Geza Lore] * Deprecate sensitivity list on public_flat_rw attributes (#6443). [Geza Lore]
* Deprecate clocker attribute and --clk option (#6463). [Geza Lore] * Deprecate clocker attribute and --clk option (#6463). [Geza Lore]
* Deprecate '--make cmake' option (#6540). [Geza Lore] * Deprecate '--make cmake' option (#6540). [Geza Lore]

View File

@ -455,6 +455,7 @@ detailed descriptions of these arguments.
--pipe-filter <command> Filter all input through a script --pipe-filter <command> Filter all input through a script
--prefix <topname> Name of top-level class --prefix <topname> Name of top-level class
--preproc-comments Include preprocessor comments in the output with -E --preproc-comments Include preprocessor comments in the output with -E
--preproc-defines Include preprocessor defines in the output with -E
--preproc-resolve Include all found modules in the output with -E --preproc-resolve Include all found modules in the output with -E
--preproc-token-limit Maximum tokens on a line allowed by preprocessor --preproc-token-limit Maximum tokens on a line allowed by preprocessor
--private Debugging; see docs --private Debugging; see docs

View File

@ -1280,6 +1280,10 @@ Summary:
With :vlopt:`-E`, show comments in preprocessor output. With :vlopt:`-E`, show comments in preprocessor output.
.. option:: --preproc-defines
With :vlopt:`-E`, show defines and undefs in preprocessor output.
.. option:: --preproc-resolve .. option:: --preproc-resolve
With :vlopt:`-E`, resolve referenced instance modules, to include With :vlopt:`-E`, resolve referenced instance modules, to include

View File

@ -1618,6 +1618,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
m_prefix = valp; m_prefix = valp;
}); });
DECL_OPTION("-preproc-comments", OnOff, &m_preprocComments); DECL_OPTION("-preproc-comments", OnOff, &m_preprocComments);
DECL_OPTION("-preproc-defines", OnOff, &m_preprocDefines);
DECL_OPTION("-preproc-resolve", OnOff, &m_preprocResolve); DECL_OPTION("-preproc-resolve", OnOff, &m_preprocResolve);
DECL_OPTION("-preproc-token-limit", CbVal, [this, fl](const char* valp) { DECL_OPTION("-preproc-token-limit", CbVal, [this, fl](const char* valp) {
m_preprocTokenLimit = std::atoi(valp); m_preprocTokenLimit = std::atoi(valp);

View File

@ -268,6 +268,7 @@ private:
bool m_pinsScBigUint = false; // main switch: --pins-sc-biguint bool m_pinsScBigUint = false; // main switch: --pins-sc-biguint
bool m_pinsUint8 = false; // main switch: --pins-uint8 bool m_pinsUint8 = false; // main switch: --pins-uint8
bool m_preprocComments = false; // main switch: --preproc-comments bool m_preprocComments = false; // main switch: --preproc-comments
bool m_preprocDefines = false; // main switch: --preproc-defines
bool m_profC = false; // main switch: --prof-c bool m_profC = false; // main switch: --prof-c
bool m_profCFuncs = false; // main switch: --prof-cfuncs bool m_profCFuncs = false; // main switch: --prof-cfuncs
bool m_profExec = false; // main switch: --prof-exec bool m_profExec = false; // main switch: --prof-exec
@ -555,6 +556,7 @@ public:
bool pinsScBigUint() const VL_MT_SAFE { return m_pinsScBigUint; } bool pinsScBigUint() const VL_MT_SAFE { return m_pinsScBigUint; }
bool pinsUint8() const { return m_pinsUint8; } bool pinsUint8() const { return m_pinsUint8; }
bool preprocComments() const { return m_preprocComments; } bool preprocComments() const { return m_preprocComments; }
bool preprocDefines() const { return m_preprocDefines; }
bool profC() const { return m_profC; } bool profC() const { return m_profC; }
bool profCFuncs() const { return m_profCFuncs; } bool profCFuncs() const { return m_profCFuncs; }
bool profExec() const { return m_profExec; } bool profExec() const { return m_profExec; }

View File

@ -307,8 +307,14 @@ void V3PreProc::selfTest() VL_MT_DISABLED { V3PreExpr::selfTest(); }
//************************************************************************* //*************************************************************************
// Defines // Defines
void V3PreProcImp::undef(const string& name) { m_defines.erase(name); } void V3PreProcImp::undef(const string& name) {
if (v3Global.opt.preprocOnly() && v3Global.opt.preprocDefines())
insertUnreadback("`undef " + name + "\n");
m_defines.erase(name);
}
void V3PreProcImp::undefineall() { void V3PreProcImp::undefineall() {
if (v3Global.opt.preprocOnly() && v3Global.opt.preprocDefines())
insertUnreadback("`undefineall\n");
for (DefinesMap::iterator nextit, it = m_defines.begin(); it != m_defines.end(); it = nextit) { for (DefinesMap::iterator nextit, it = m_defines.begin(); it != m_defines.end(); it = nextit) {
nextit = it; nextit = it;
++nextit; ++nextit;
@ -348,6 +354,18 @@ FileLine* V3PreProcImp::defFileline(const string& name) {
void V3PreProcImp::define(FileLine* fl, const string& name, const string& value, void V3PreProcImp::define(FileLine* fl, const string& name, const string& value,
const string& params, bool cmdline) { const string& params, bool cmdline) {
UINFO(4, "DEFINE '" << name << "' as '" << value << "' params '" << params << "'"); UINFO(4, "DEFINE '" << name << "' as '" << value << "' params '" << params << "'");
if (v3Global.opt.preprocOnly() && v3Global.opt.preprocDefines()) {
// Any newlines in the string must have backslash escape so can re-parse properly
// If there was a comment with backslash, it got stripped because IEEE says
// the backslash is not part of the value
string out;
out.reserve(value.size());
for (string::size_type pos = 0; pos < value.size(); ++pos) {
if (value[pos] == '\n' && (pos == 0 || value[pos - 1] != '\\')) out += '\\';
out += value[pos];
}
insertUnreadback("`define " + name + params + (out.empty() ? "" : " ") + out + "\n");
}
if (!V3LanguageWords::isKeyword("`"s + name).empty()) { if (!V3LanguageWords::isKeyword("`"s + name).empty()) {
fl->v3error("Attempting to define built-in directive: '`" << name fl->v3error("Attempting to define built-in directive: '`" << name
<< "' (IEEE 1800-2023 22.5.1)"); << "' (IEEE 1800-2023 22.5.1)");
@ -1335,7 +1353,7 @@ int V3PreProcImp::getStateToken() {
// DEFVALUE is terminated by a return, but lex can't return both tokens. // DEFVALUE is terminated by a return, but lex can't return both tokens.
// Thus, we emit a return here. // Thus, we emit a return here.
yyourtext(s_newlines.c_str(), s_newlines.length()); yyourtext(s_newlines.c_str(), s_newlines.length());
return (VP_WHITE); return VP_WHITE;
} }
case ps_DEFPAREN: { case ps_DEFPAREN: {
if (tok == VP_TEXT && yyourleng() == 1 && yyourtext()[0] == '(') { if (tok == VP_TEXT && yyourleng() == 1 && yyourtext()[0] == '(') {

View File

@ -1079,3 +1079,17 @@ string boo = "testx,ytest x x,y";
string boo = "testtest x,y xquux(test)"; string boo = "testtest x,y xquux(test)";
`line 757 "t/t_preproc.v" 0 `line 757 "t/t_preproc.v" 0
`line 760 "t/t_preproc.v" 0
`line 769 "t/t_preproc.v" 0

View File

@ -753,3 +753,15 @@ predef `SV_COV_PARTIAL 2
`quux(`bar(`a,`a)) `quux(`bar(`a,`a))
`quux(`baz(`a,`bar(x,`a))) `quux(`baz(`a,`bar(x,`a)))
`quux(`baz(`bar(`a,x), quux(`foo))) `quux(`baz(`bar(`a,x), quux(`foo)))
//======================================================================
// Define with --preproc-defines needs to keep backslashes
`define uvm_a(x) foo x bar
`define uvm_imp_decl(SFX) \
class uvm_master_imp``SFX \
`uvm_a(SFX, RSP, t) // rsp \
\
`uvm_a(SFX, REQ, t) // req \
\
endclass

View File

@ -1084,3 +1084,17 @@ string boo = "testx,ytest x x,y";
string boo = "testtest x,y xquux(test)"; string boo = "testtest x,y xquux(test)";
`line 757 "t/t_preproc.v" 0 `line 757 "t/t_preproc.v" 0
//======================================================================
// Define with --preproc-defines needs to keep backslashes
`line 760 "t/t_preproc.v" 0
`line 769 "t/t_preproc.v" 0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
#!/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_preproc.v"
stdout_filename = os.path.join(test.obj_dir, test.name + "__test.vpp")
test.compile(verilator_flags2=['-DDEF_A0 -DPREDEF_COMMAND_LINE -E --preproc-defines'],
verilator_make_gmake=False,
make_top_shell=False,
make_main=False,
stdout_filename=stdout_filename)
test.files_identical(stdout_filename, test.golden_filename)
test.passes()

View File

@ -27,5 +27,13 @@
`define foo test `define foo test
`define quux(x) `qux(`"x`") `define quux(x) `qux(`"x`")
`define qux(x) string boo = x; `define qux(x) string boo = x;
`define uvm_a(x) foo x bar
`define uvm_imp_decl(SFX) \
class uvm_master_imp``SFX \
`uvm_a(SFX, RSP, t)
\
`uvm_a(SFX, REQ, t)
\
endclass
`define verilator 1 `define verilator 1
`define verilator3 1 `define verilator3 1