Add t_dist_docs_options checks, and fix related docs and coverage issues

This commit is contained in:
Wilson Snyder 2025-10-25 09:57:18 -04:00
parent e21dd04159
commit dd76a5b8ba
10 changed files with 221 additions and 65 deletions

View File

@ -400,7 +400,9 @@ detailed descriptions of these arguments.
--getenv <var> Get environment variable with defaults
--help Show this help
--hierarchical Enable hierarchical Verilation
--hierarchical-params-file <name> Internal option that specifies parameters file for hier blocks
--hierarchical-block <block> Internal use only for --hierarchical
--hierarchical-child <block> Internal use only for --hierarchical
--hierarchical-params-file <name> Internal option that specifies parameters file for hier blocks
--hierarchical-threads <threads> Number of threads for hierarchical scheduling
-I<dir> Directory to search for includes
--if-depth <value> Tune IFDEPTH warning
@ -418,6 +420,7 @@ detailed descriptions of these arguments.
-LDFLAGS <flags> Linker pre-object arguments for makefile
--lib-create <name> Create a DPI library
+libext+<ext>+[ext]... Extensions for finding modules
+librescan Ignored for compatibility
--lint-only Lint, but do not make output
--localize-max-size <value> Tune localize optimization variable size
--main Generate C++ main() file
@ -432,6 +435,8 @@ detailed descriptions of these arguments.
+notimingchecks Ignored
-o <executable> Name of final executable
-O0 Disable optimizations
-O1 Default optimizations
-O2 Stronger optimizations
-O3 High-performance optimizations
-O<optimization-letter> Selectable optimizations
--output-groups <numfiles> Group .cpp files into larger ones

View File

@ -623,6 +623,10 @@ Summary:
.. option:: -fno-const-eager
.. option:: -fno-dead-assigns
.. option:: -fno-dead-cells
.. option:: -fno-dedup
.. option:: -fno-dfg
@ -812,6 +816,14 @@ Summary:
:option:`/*verilator&32;hier_block*/` metacomment is ignored. See
:ref:`Hierarchical Verilation`.
.. option:: --hierarchical-block <block>
Internal use only, for :vlopt:`--hierarchical`.
.. option:: --hierarchical-child <block>
Internal use only, for :vlopt:`--hierarchical`.
.. option:: --hierarchical-params-file <filename>
Rarely needed - internal use. Internal flag inserted used during
@ -964,6 +976,10 @@ Summary:
"+libext+" is relatively standard across Verilog tools. Defaults to
".v+.sv".
.. option:: +librescan
Ignored for compatibility with other simulators.
.. option:: --lint-only
Check the files for lint violations only, do not create any other
@ -1072,6 +1088,15 @@ Summary:
Disables optimization of the model.
.. option:: -O1
Enables default optimization of the model. This is the default
optimization level.
.. option:: -O2
Enables stronger than default optimization of the model.
.. option:: -O3
Enables slow optimizations for the code Verilator itself generates (as

View File

@ -233,6 +233,12 @@ void V3OptionParser::finalize() {
m_pimpl->m_isFinalized = true;
}
void V3OptionParser::dumpOptions() {
for (const auto& opt : m_pimpl->m_spellCheck.candidates()) {
std::cout << "OPTION: \"" + opt + "\"\n";
}
}
V3OptionParser::V3OptionParser()
: m_pimpl{new Impl{}} {}

View File

@ -81,6 +81,7 @@ public:
void addSuggestionCandidate(const string& s) VL_MT_DISABLED;
// Call this function after all options are registered.
void finalize() VL_MT_DISABLED;
void dumpOptions() VL_MT_DISABLED;
// CONSTRUCTORS
V3OptionParser() VL_MT_DISABLED;

View File

@ -1335,9 +1335,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
v3fatalSrc("--debug-fatal-src");
}).undocumented(); // See also --debug-abort
DECL_OPTION("-debug-leak", OnOff, &m_debugLeak);
DECL_OPTION("-debug-nondeterminism", OnOff, &m_debugNondeterminism);
DECL_OPTION("-debug-nondeterminism", OnOff, &m_debugNondeterminism).undocumented();
DECL_OPTION("-debug-options", OnOff, &m_debugOptions).undocumented();
DECL_OPTION("-debug-partition", OnOff, &m_debugPartition).undocumented();
DECL_OPTION("-debug-preproc-passthru", OnOff, &m_debugPreprocPassthru);
DECL_OPTION("-debug-preproc-passthru", OnOff, &m_debugPreprocPassthru).undocumented();
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
@ -1466,7 +1467,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
DECL_OPTION("-I", CbPartialMatch,
[this, &optdir](const char* optp) { addIncDirUser(parseFileArg(optdir, optp)); });
DECL_OPTION("-if-depth", Set, &m_ifDepth);
DECL_OPTION("-ignc", OnOff, &m_ignc);
DECL_OPTION("-ignc", OnOff, &m_ignc).undocumented();
DECL_OPTION("-inline-mult", Set, &m_inlineMult);
DECL_OPTION("-instr-count-dpi", CbVal, [this, fl](int val) {
m_instrCountDpi = val;
@ -1546,7 +1547,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
DECL_OPTION("-o", Set, &m_exeName);
DECL_OPTION("-order-clock-delay", CbOnOff, [fl](bool /*flag*/) {
fl->v3warn(DEPRECATED, "Option order-clock-delay is deprecated and has no effect.");
});
}).undocumented();
DECL_OPTION("-output-groups", CbVal, [this, fl](const char* valp) {
m_outputGroups = std::atoi(valp);
if (m_outputGroups < -1) fl->v3error("--output-groups must be >= -1: " << valp);
@ -1599,8 +1600,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
DECL_OPTION("-prof-cfuncs", CbCall, [this]() { m_profC = m_profCFuncs = true; });
DECL_OPTION("-prof-exec", OnOff, &m_profExec);
DECL_OPTION("-prof-pgo", OnOff, &m_profPgo);
DECL_OPTION("-profile-cfuncs", CbCall,
[this]() { m_profC = m_profCFuncs = true; }); // Renamed
DECL_OPTION("-profile-cfuncs", CbCall, [this]() {
m_profC = m_profCFuncs = true;
}).undocumented(); // Renamed
DECL_OPTION("-protect-ids", OnOff, &m_protectIds);
DECL_OPTION("-protect-key", Set, &m_protectKey);
DECL_OPTION("-protect-lib", CbVal, [this, fl](const char* valp) {
@ -1741,7 +1743,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
fl->v3warn(DEPRECATED, "Option --trace-fst-thread is deprecated. "
"Use --trace-fst with --trace-threads > 0.");
if (m_traceThreads == 0) m_traceThreads = 1;
});
}).undocumented();
DECL_OPTION("-trace-max-array", Set, &m_traceMaxArray);
DECL_OPTION("-trace-max-width", Set, &m_traceMaxWidth);
DECL_OPTION("-trace-params", OnOff, &m_traceParams);
@ -1756,7 +1758,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
DECL_OPTION("-trace-vcd", CbCall, [this]() { m_traceEnabledVcd = true; });
DECL_OPTION("-U", CbPartialMatch, &V3PreShell::undef);
DECL_OPTION("-underline-zero", OnOff, &m_underlineZero); // Deprecated
DECL_OPTION("-underline-zero", OnOff, &m_underlineZero).undocumented(); // Deprecated
DECL_OPTION("-no-unlimited-stack", CbCall, []() {}); // Processed only in bin/verilator shell
DECL_OPTION("-unroll-count", Set, &m_unrollCount).undocumented(); // Optimization tweak
DECL_OPTION("-unroll-stmts", Set, &m_unrollStmts).undocumented(); // Optimization tweak
@ -1968,6 +1970,11 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
++i;
}
}
if (m_debugOptions) {
parser.dumpOptions();
v3Global.vlExit(0);
}
}
//======================================================================

View File

@ -239,6 +239,7 @@ private:
bool m_debugExitUvm23 = false; // main switch: --debug-exit-uvm23
bool m_debugLeak = true; // main switch: --debug-leak
bool m_debugNondeterminism = false; // main switch: --debug-nondeterminism
bool m_debugOptions = false; // main switch: --debug-options
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

View File

@ -262,6 +262,7 @@ public:
}
}
static void selfTest();
const std::vector<std::string> candidates() const { return m_candidates; }
private:
static EditDistance editDistance(const string& s, const string& t);

View File

@ -15,10 +15,10 @@ test.top_filename = "t/t_gen_alw.v" # Use any top file
test.init_benchmarksim()
# As an example, compile and simulate the top file with varying optimization level
l_opts = [1, 2, 3]
l_opts = ['-O0', '-O1', '-O2', '-O3']
for l_opt in l_opts:
test.compile(benchmarksim=1, v_flags2=["-O" + str(l_opt)])
test.compile(benchmarksim=1, v_flags2=[l_opt])
test.execute()

View File

@ -11,22 +11,63 @@ import vltest_bootstrap
test.scenarios('dist')
Waivers = [
Doc_Waivers = [
'+verilator+prof+threads+file+', # Deprecated
'+verilator+prof+threads+start+', # Deprecated
'+verilator+prof+threads+window+', # Deprecated
'-clk', # Deprecated
'-fdfg-synthesize-all', # Mostly used for testing
'-fno-', # Documented differently
'-no-clk', # Deprecated
'-no-lineno', # Deprecated
'-no-order-clock-delay', # Deprecated
'-lineno', # Deprecated
'-order-clock-delay', # Deprecated
'-prof-threads', # Deprecated
]
Test_Waivers = [
# Covered:
'-G', # Covered; other text fallows option letter
'-O', # Covered; other text fallows option letter
'-U', # Covered; other text fallows option letter
'-gdb', # Covered: no way to test, part of --gdbbt
'-rr', # Not testing; not requiring rr installation
# Need testing:
'-Wno-lint',
'-Wno-style',
'-Wwarn-lint',
'-annotate-all',
'-annotate-min',
'-converge-limit',
'-coverage-underscore',
'-default-language',
'-dump-graph',
'-dumpi-tree-json',
'-facyc-simp', # Need test of -fno-...
'-fassemble', # Need test of -fno-...
'-fcase', # Need test of -fno-...
'-fcombine', # Need test of -fno-...
'-fconst', # Need test of -fno-...
'-fdedup', # Need test of -fno-...
'-fdfg-peephole', # Need test of -fno-...
'-fdfg-peephole-', # Need test of -fno-...
'-ffunc-opt-balance-cat', # Need test of -fno-...
'-ffunc-opt-split-cat', # Need test of -fno-...
'-flife', # Need test of -fno-...
'-flife-post', # Need test of -fno-...
'-fmerge-cond', # Need test of -fno-...
'-freloop', # Need test of -fno-...
'-fsubst', # Need test of -fno-...
'-fsubst-const', # Need test of -fno-...
'-ftable', # Need test of -fno-...
'-json-ids', # Need test of -no-json-ids
'-private',
'-trace-depth',
]
def get_summary_opts():
args = {}
Sums = {}
Docs = {}
Srcs = {}
Tests = {}
def read_sums():
for filename in test.glob_some(test.root + "/bin/*"):
with open(filename, "r", encoding="latin-1") as fh:
on = False
@ -42,19 +83,19 @@ def get_summary_opts():
on = False
elif on and m1:
opt = opt_clean(m1.group(1))
key = opt_key(opt)
if test.verbose:
print("S '" + opt + "' " + line)
args[opt] = filename + ":" + str(lineno)
print("A '" + opt + "' " + line)
Sums[key] = filename + ":" + str(lineno) + ": " + opt
elif m2:
opt = opt_clean(m2.group(1))
key = opt_key(opt)
if test.verbose:
print("S '" + opt + "' " + line)
args[opt] = filename + ":" + str(lineno)
return args
print("A '" + opt + "' " + line)
Sums[key] = filename + ":" + str(lineno) + ": " + opt
def get_docs_opts():
args = {}
def read_docs():
for filename in test.glob_some(test.root + "/docs/guide/*.rst"):
with open(filename, "r", encoding="latin-1") as fh:
lineno = 0
@ -68,10 +109,60 @@ def get_docs_opts():
m = re.search(r':vlopt:`((-|\+)+[^ `]+)', line)
if m:
opt = opt_clean(m.group(1))
key = opt_key(opt)
if test.verbose:
print("D '" + opt + "' " + line)
args[opt] = filename + ":" + str(lineno)
return args
Docs[key] = filename + ":" + str(lineno) + ": " + opt
def read_srcs():
filename = "bin/verilator --debug-options"
opts = test.run_capture("perl " + os.environ["VERILATOR_ROOT"] + "/bin/verilator" +
" --debug-options 2>&1")
lineno = 0
for line in opts.split("\n"):
lineno += 1
m1 = re.search(r'OPTION: "([^"]+)"', line)
if m1:
opt = opt_clean(m1.group(1))
key = opt_key(opt)
if re.match(r'-Werror-[A-Z ]', opt):
continue
if re.match(r'-Wno-[A-Z ]', opt):
continue
if re.match(r'-Wwarn-[A-Z ]', opt):
continue
if test.verbose:
print("S '" + opt + "' " + line)
Srcs[key] = filename + ":" + str(lineno) + ": " + opt
if len(Srcs) < 5:
test.error("Didn't parse any options")
return Srcs
def read_tests():
filename = "test_regress/t/*.py"
for filename in (test.glob_some(test.root + "/test_regress/t/*.py")):
if "t_dist_docs_options" in filename: # Avoid our own suppressions
continue
with open(filename, 'r', encoding="latin-1") as fh:
lineno = 0
for line in fh:
lineno += 1
line = line.lstrip().rstrip()
for opt in re.findall(r'[-+]+[-+a-zA-Z0-9]+', line):
opt = opt_clean(opt)
key = opt_key(opt)
if test.verbose:
print("T '" + opt + "' " + line)
Tests[key] = filename + ":" + str(lineno) + ": " + opt
# For e.g. +verilator+seed+<something> and -dumpi-<#>
pos = max(opt.rfind('+'), opt.rfind('-'))
if pos > 1:
subkey = opt[:pos + 1]
if test.verbose:
print("t '" + subkey + "' " + line)
Tests[subkey] = filename + ":" + str(lineno) + ": " + opt
def opt_clean(opt):
@ -81,53 +172,68 @@ def opt_clean(opt):
return opt
def alt_names(opt):
opts = [opt]
if re.search(r'^-', opt):
opts.append("-no" + opt)
m = re.search(r'^-no(-.*)', opt)
if m:
opts.append(m.group(1))
return opts
def opt_key(opt):
opt = opt_clean(opt)
opt = re.sub(r'^-fno-', '-f', opt)
opt = re.sub(r'^-no-', '-', opt)
return opt
if not os.path.exists(test.root + "/.git"):
test.skip("Not in a git repository")
sums = get_summary_opts()
docs = get_docs_opts()
read_sums()
read_docs()
read_srcs()
read_tests()
both = {}
both.update(sums)
both.update(docs)
both.update(Sums)
both.update(Docs)
both.update(Srcs)
waiver = {k: 1 for k in Waivers}
doc_waiver = {k: 1 for k in Doc_Waivers}
for opt in sorted(both.keys()):
if opt in waiver:
if opt in doc_waiver:
continue
sum_ok = False
docs_ok = False
for alt in alt_names(opt):
if alt in sums:
sum_ok = True
if test.verbose:
print(str(sum_ok) + " SAC '" + opt + "' -> '" + alt + "'")
if re.search(r'-fno-', opt): # Minimal-documented optimization option
sum_ok = True
for alt in alt_names(opt):
if alt in docs:
docs_ok = True
if test.verbose:
print(str(docs_ok) + " DAC '" + opt + "' -> '" + alt + "'")
if not sum_ok:
test.error(docs[opt] + ": Option documented in docs/guide '" + opt +
"' not found in bin/* ARGUMENT SUMMARY documentation")
elif not docs_ok:
test.error(sums[opt] + ": Option documented in bin/ ARGUMENT SUMMARY '" + opt +
"' not found in docs/guide documentation")
elif test.verbose:
print(": ok '" + opt)
is_in = []
not_in = []
summ = None
if opt in Sums:
summ = Sums[opt]
is_in.append("summary " + summ)
else:
if not re.match(r'-f', opt):
not_in.append("ARGUMENT SUMMARY in bin/verilator or bin/verilator_coverage")
doc = None
if opt in Docs:
doc = Docs[opt]
is_in.append("documentation " + doc)
else:
not_in.append("documentation in docs/guide/exe_*.rst")
src = None
if opt in Srcs:
src = Srcs[opt]
is_in.append("sources " + src)
# Ok if not in sources
if opt in Tests:
if opt in Test_Waivers:
print("Unnecessary Test_Waiver for option: '" + opt + "'")
else:
if opt in Test_Waivers:
is_in.append("Test_Waiver for test_regress/t/*.py")
else:
not_in.append("uncovered in test_regress/t/*.py")
if not_in:
test.error_keep_going("Option '" + opt + "' has inconsistent references\n" +
" Missing in " + "\n Missing in ".join(not_in) + "\n Found in " +
"\n Found in ".join(is_in))
test.passes()

View File

@ -11,7 +11,11 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile(v_flags2=["-f t/t_flag_define.vc -DCMD_DEF -DCMD_UNDEF -UCMD_UNDEF +define+CMD_DEF2"])
# We also test +librescan and +notimingchecks here, which are NOPs
test.compile(v_flags2=[
"-f t/t_flag_define.vc -DCMD_DEF -DCMD_UNDEF -UCMD_UNDEF +define+CMD_DEF2", "+librescan",
"+notimingchecks"
])
test.execute()