[dvsim] Improve --help message
This should contain no functional changes, but improves the output
from dvsim.py --help.
Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/util/dvsim/dvsim.py b/util/dvsim/dvsim.py
index 0f3e40d..9c2d66f 100755
--- a/util/dvsim/dvsim.py
+++ b/util/dvsim/dvsim.py
@@ -2,14 +2,21 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
-"""
-dvsim is a command line tool to deploy regressions for design verification. It uses hjson as the
-format for specifying what to build and run. It is an end-to-end regression manager that can deploy
-multiple builds (where some tests might need different set of compile time options requiring a
-uniquely build sim executable) in parallel followed by tests in parallel using the load balancer
-of your choice. dvsim is built to be tool-agnostic so that you can easily switch between tools
-available at your disposal. dvsim uses fusesoc as the starting step to resolve all inter-package
-dependencies and provide us with a filelist that will be consumed by the sim tool.
+"""dvsim is a command line tool to deploy ASIC tool flows such as regressions
+for design verification (DV), formal property verification (FPV), linting and
+synthesis.
+
+It uses hjson as the format for specifying what to build and run. It is an
+end-to-end regression manager that can deploy multiple builds (where some tests
+might need different set of compile time options requiring a uniquely build sim
+executable) in parallel followed by tests in parallel using the load balancer
+of your choice.
+
+dvsim is built to be tool-agnostic so that you can easily switch between the
+tools at your disposal. dvsim uses fusesoc as the starting step to resolve all
+inter-package dependencies and provide us with a filelist that will be consumed
+by the sim tool.
+
"""
import argparse
@@ -18,6 +25,7 @@
import os
import subprocess
import sys
+import textwrap
from signal import SIGINT, signal
import Deploy
@@ -138,296 +146,317 @@
exit(1)
-def main():
+def wrapped_docstring():
+ '''Return a text-wrapped version of the module docstring'''
+ paras = []
+ para = []
+ for line in __doc__.strip().split('\n'):
+ line = line.strip()
+ if not line:
+ if para:
+ paras.append('\n'.join(para))
+ para = []
+ else:
+ para.append(line)
+ if para:
+ paras.append('\n'.join(para))
+
+ return '\n\n'.join(textwrap.fill(p) for p in paras)
+
+
+def parse_args():
parser = argparse.ArgumentParser(
- description=__doc__,
+ description=wrapped_docstring(),
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("cfg",
metavar="<cfg-hjson-file>",
help="""Configuration hjson file.""")
- parser.add_argument("-i",
- "--items",
- nargs="*",
- default=["sanity"],
- metavar="regr1, regr2, regr3|test1, test2, test3, ...",
- help="""Indicate which regressions or tests to run.""")
-
- parser.add_argument(
- "-l",
- "--list",
- nargs="*",
- choices=_LIST_CATEGORIES,
- metavar="build_modes|run_modes|tests|regressions",
- help=
- """List the available build_modes / run_modes / tests / regressions for use."""
- )
-
- parser.add_argument("-t",
- "--tool",
- metavar="vcs|xcelium|ascentlint|veriblelint|dc|...",
- help="Override the tool that is set in hjson file")
-
- parser.add_argument(
- "--select-cfgs",
- nargs="*",
- metavar="cfg1, cfg2, cfg3, ...",
- help="""Specifies which cfg(s) of the master cfg shall be processed.
- If this switch is not specified, dvsim will process all cfgs specified in
- the master cfg list.""")
-
- parser.add_argument(
- "-sr",
- "--scratch-root",
- metavar="path",
- help="""root scratch directory path where all build / run drectories go;
- by default, the tool will create the {scratch_path} = {scratch_root}/{dut}
- directory if it doesn't already exist; under {scratch_path}, there will be
- {compile_set} set of directories where all the build outputs go and
- {test_name} set of directories where the test outputs go"""
- )
-
- parser.add_argument("-pr",
- "--proj-root",
- metavar="path",
- help="""Specify the root directory of the project.
- If this option is not passed, the tool will assume that this is
- a local GitHub repository and will attempt to automatically find
- the root directory.""")
-
- parser.add_argument(
- "-br",
- "--branch",
- metavar="<branch-name>",
- help=
- """This variable is used to construct the scratch path directory name. If not
- specified, it defaults to the GitHub branch name. The idea is to uniquefy the
- scratch paths between different branches.""")
-
- parser.add_argument(
- "-bo",
- "--build-opts",
- nargs="+",
- default=[],
- metavar="",
- help="""Pass additional build options over the command line;
- note that if there are multiple compile sets identified to be built,
- these options will be passed on to all of them""")
-
- parser.add_argument(
- "-bm",
- "--build-modes",
- nargs="+",
- default=[],
- metavar="",
- help="""Set build modes on the command line for all tests run as a part
- of the regression.""")
-
- parser.add_argument(
- "-ro",
- "--run-opts",
- nargs="+",
- default=[],
- metavar="",
- help="""Pass additional run time options over the command line;
- these options will be passed on to all tests scheduled to be run"""
- )
-
- parser.add_argument(
- "-rm",
- "--run-modes",
- nargs="+",
- default=[],
- metavar="",
- help="""Set run modes on the command line for all tests run as a part
- of the regression.""")
-
- parser.add_argument(
- "-bu",
- "--build-unique",
- action='store_true',
- help=
- """By default, under the {scratch} directory, there is a {compile_set}
- directory created where the build output goes; this can be
- uniquified by appending the current timestamp. This is suitable
- for the case when a test / regression already running and you want
- to run something else from a different terminal without affecting
- the previous one""")
-
- parser.add_argument(
- "--build-only",
- action='store_true',
- help="Only build the simulation executables for the givem items.")
-
- parser.add_argument(
- "--run-only",
- action='store_true',
- help="Assume sim exec is available and proceed to run step")
-
- parser.add_argument(
- "-s",
- "--seeds",
- nargs="+",
- default=[],
- metavar="seed0 seed1 ...",
- help=
- """Run tests with a specific seeds. Note that these specific seeds are applied to
- items being run in the order they are passed.""")
-
- parser.add_argument(
- "--fixed-seed",
- type=int,
- help=
- """Run all items with a fixed seed value. This option enforces --reseed 1."""
- )
-
- parser.add_argument(
- "-r",
- "--reseed",
- type=int,
- metavar="N",
- help="""Repeat tests with N iterations with different seeds""")
-
- parser.add_argument("-rx",
- "--reseed-multiplier",
- type=int,
- default=1,
- metavar="N",
- help="""Multiplier for existing reseed values.""")
-
- parser.add_argument("-w",
- "--waves",
- action='store_true',
- help="Enable dumping of waves")
-
- parser.add_argument("-d",
- "--dump",
- choices=["fsdb", "shm", "vpd"],
- help=("Format to dump waves for simulation. If Verdi "
- "is installed (detected by searching PATH) this "
- "defaults to fsdb. Otherwise, defaults to shm "
- "for Xcelium or vpd for VCS."))
-
- parser.add_argument("-mw",
- "--max-waves",
- type=int,
- default=5,
- metavar="N",
- help="""Enable dumping of waves for at most N tests;
- this includes tests scheduled for run AND automatic rerun"""
- )
-
- parser.add_argument("-c",
- "--cov",
- action='store_true',
- help="turn on coverage collection")
-
- parser.add_argument(
- "--cov-merge-previous",
- action='store_true',
- help="""Applicable when --cov switch is enabled. If a previous cov
- database directory exists, this switch will cause it to be merged with
- the current cov database.""")
-
- parser.add_argument(
- "--cov-analyze",
- action='store_true',
- help="Analyze the coverage from the last regression result.")
-
- parser.add_argument("-p",
- "--profile",
- nargs='?',
- const='time',
- choices=["time", "mem"],
- help="Turn on simulation profiling")
-
- parser.add_argument("--xprop-off",
- action='store_true',
- help="Turn off Xpropagation")
-
- parser.add_argument("--job-prefix",
- default="",
- metavar="job-prefix",
- help="Job prefix before deploying the tool commands.")
-
- parser.add_argument("--purge",
- action='store_true',
- help="Clean the scratch directory before running.")
-
- parser.add_argument(
- "-mo",
- "--max-odirs",
- type=int,
- default=5,
- metavar="N",
- help="""When tests are run, the older runs are backed up. This switch
- limits the number of backup directories being maintained.""")
-
- parser.add_argument(
- "--no-rerun",
- action='store_true',
- help=
- """By default, failing tests will be automatically be rerun with waves;
- this option will prevent the rerun from being triggered""")
-
- parser.add_argument("-v",
- "--verbosity",
- default="l",
- choices=["n", "l", "m", "h", "d"],
- help="""Set verbosity to none/low/medium/high/debug;
- This will override any setting added to any of the hjson files
- used for config""")
-
- parser.add_argument(
- "--verbose",
- nargs="?",
- choices=['default', 'debug'],
- default=None,
- const="default",
- metavar="debug",
- help="""Print verbose dvsim tool messages. If 'debug' is passed, then the
- volume of messages is ven higher.""")
-
parser.add_argument("--version",
action='store_true',
help="Print version and exit")
- parser.add_argument(
- "-n",
- "--dry-run",
- action='store_true',
- help=
- "Print dvsim tool messages only, without actually running any command")
+ parser.add_argument("--tool", "-t",
+ default="",
+ help=("Explicitly set the tool to use. This is "
+ "optional for running simulations (where it can "
+ "be set in an .hjson file), but is required for "
+ "other flows. Possible tools include: vcs, "
+ "xcelium, ascentlint, verible, dc."))
- parser.add_argument(
- "--map-full-testplan",
- action='store_true',
- help="Force complete testplan annotated results to be shown at the end."
- )
+ parser.add_argument("--list", "-l",
+ nargs="*",
+ metavar='CAT',
+ choices=_LIST_CATEGORIES,
+ help=('Parse the the given .hjson config file, list '
+ 'the things that can be run, then exit. The '
+ 'list can be filtered with a space-separated '
+ 'of categories from: {}.'
+ .format(', '.join(_LIST_CATEGORIES))))
- parser.add_argument(
- "--publish",
- action='store_true',
- help="Publish results to the reports.opentitan.org web server.")
+ whatg = parser.add_argument_group('Choosing what to run')
- parser.add_argument(
- "-pi",
- "--print-interval",
- type=int,
- default=10,
- metavar="N",
- help="""Interval in seconds. Print status every N seconds.""")
+ whatg.add_argument("-i",
+ "--items",
+ nargs="*",
+ default=["sanity"],
+ help=('Specify the regressions or tests to run. '
+ 'Defaults to "sanity", but can be a '
+ 'space separated list of test or regression '
+ 'names.'))
- parser.add_argument(
- "-mp",
- "--max-parallel",
- type=int,
- default=16,
- metavar="N",
- help="""Run only upto a fixed number of builds/tests at a time.""")
+ whatg.add_argument("--select-cfgs",
+ nargs="*",
+ metavar="CFG",
+ help=('The .hjson file is a master config. Only run '
+ 'the given configs from it. If this argument is '
+ 'not used, dvsim will process all configs listed '
+ 'in a master config.'))
- args = parser.parse_args()
+ disg = parser.add_argument_group('Dispatch options')
+
+ disg.add_argument("--job-prefix",
+ default="",
+ metavar="PFX",
+ help=('Prepend this string when running each tool '
+ 'command.'))
+
+ disg.add_argument("--max-parallel", "-mp",
+ type=int,
+ default=16,
+ metavar="N",
+ help=('Run only up to N builds/tests at a time. '
+ 'Default value 16.'))
+
+ pathg = parser.add_argument_group('File management')
+
+ pathg.add_argument("--scratch-root", "-sr",
+ metavar="PATH",
+ help=('Destination for build / run directories. If not '
+ 'specified, uses the path in the SCRATCH_ROOT '
+ 'environment variable, if set, or ./scratch '
+ 'otherwise.'))
+
+ pathg.add_argument("--proj-root", "-pr",
+ metavar="PATH",
+ help=('The root directory of the project. If not '
+ 'specified, dvsim will search for a git '
+ 'repository containing the current directory.'))
+
+ pathg.add_argument("--branch", "-br",
+ metavar='B',
+ help=('By default, dvsim creates files below '
+ '{scratch-root}/{dut}.{flow}.{tool}/{branch}. '
+ 'If --branch is not specified, dvsim assumes the '
+ 'current directory is a git repository and uses '
+ 'the name of the current branch.'))
+
+ pathg.add_argument("--max-odirs", "-mo",
+ type=int,
+ default=5,
+ metavar="N",
+ help=('When tests are run, older runs are backed '
+ 'up. Discard all but the N most recent (defaults '
+ 'to 5).'))
+
+ pathg.add_argument("--purge",
+ action='store_true',
+ help="Clean the scratch directory before running.")
+
+ buildg = parser.add_argument_group('Options for building')
+
+ buildg.add_argument("--build-only",
+ action='store_true',
+ help=('Stop after building executables for the given '
+ 'items.'))
+
+ buildg.add_argument("--build-unique", "-bu",
+ action='store_true',
+ help=('Append a timestamp to the directory in which '
+ 'files are built. This is suitable for the case '
+ 'when another test is already running and you '
+ 'want to run something else from a different '
+ 'terminal without affecting it.'))
+
+ buildg.add_argument("--build-opts", "-bo",
+ nargs="+",
+ default=[],
+ metavar="OPT",
+ help=('Additional options passed on the command line '
+ 'each time a build tool is run.'))
+
+ buildg.add_argument("--build-modes", "-bm",
+ nargs="+",
+ default=[],
+ metavar="MODE",
+ help=('The options for each build_mode in this list '
+ 'are applied to all build and run targets.'))
+
+ rung = parser.add_argument_group('Options for running')
+
+ rung.add_argument("--run-only",
+ action='store_true',
+ help=('Skip the build step (assume that simulation '
+ 'executables have already been built).'))
+
+ rung.add_argument("--run-opts", "-ro",
+ nargs="+",
+ default=[],
+ metavar="OPT",
+ help=('Additional options passed on the command line '
+ 'each time a test is run.'))
+
+ rung.add_argument("--run-modes", "-rm",
+ nargs="+",
+ default=[],
+ metavar="MODE",
+ help=('The options for each run_mode in this list are '
+ 'applied to each simulation run.'))
+
+ rung.add_argument("--profile", "-p",
+ choices=['time', 'mem'],
+ metavar="P",
+ help=('Turn on simulation profiling (where P is time '
+ 'or mem).'))
+
+ rung.add_argument("--xprop-off",
+ action='store_true',
+ help="Turn off X-propagation in simulation.")
+
+ rung.add_argument("--no-rerun",
+ action='store_true',
+ help=("Disable the default behaviour, where failing "
+ "tests are automatically rerun with waves "
+ "enabled."))
+
+ rung.add_argument("--verbosity", "-v",
+ default="l",
+ choices=['n', 'l', 'm', 'h', 'd'],
+ metavar='V',
+ help=('Set UVM verbosity to none (n), low (l; the '
+ 'default), medium (m), high (h) or debug (d). '
+ 'This overrides any setting in the config files.'))
+
+ seedg = parser.add_argument_group('Test seeds')
+
+ seedg.add_argument("--seeds", "-s",
+ nargs="+",
+ default=[],
+ metavar="S",
+ help=('A list of seeds for tests. Note that these '
+ 'specific seeds are applied to items being run '
+ 'in the order they are passed.'))
+
+ seedg.add_argument("--fixed-seed",
+ type=int,
+ metavar='S',
+ help=('Run all items with the seed S. This implies '
+ '--reseed 1.'))
+
+ seedg.add_argument("--reseed", "-r",
+ type=int,
+ default=-1,
+ metavar="N",
+ help=('Override any reseed value in the test '
+ 'configuration and run each test N times, with '
+ 'a new seed each time.'))
+
+ seedg.add_argument("--reseed-multiplier", "-rx",
+ type=int,
+ default=1,
+ metavar="N",
+ help=('Scale each reseed value in the test '
+ 'configuration by N. This allows e.g. running '
+ 'the tests 10 times as much as normal while '
+ 'maintaining the ratio of numbers of runs '
+ 'between different tests.'))
+
+ waveg = parser.add_argument_group('Dumping waves')
+
+ waveg.add_argument("--waves", "-w",
+ action='store_true',
+ help="Enable dumping of waves")
+
+ waveg.add_argument("-d",
+ "--dump",
+ choices=["fsdb", "shm", "vpd"],
+ help=("Format to dump waves for simulation. The default "
+ "format depends on the tool. With VCS, this "
+ "defaults to fsdb if Verdi is installed, else "
+ "vpd. With Xcelium, defaults to shm."))
+
+ waveg.add_argument("--max-waves", "-mw",
+ type=int,
+ default=5,
+ metavar="N",
+ help=('Only dump waves for the first N tests run. This '
+ 'includes both tests scheduled for run and those '
+ 'that are automatically rerun.'))
+
+ covg = parser.add_argument_group('Generating simulation coverage')
+
+ covg.add_argument("--cov", "-c",
+ action='store_true',
+ help="Enable collection of coverage data.")
+
+ covg.add_argument("--cov-merge-previous",
+ action='store_true',
+ help=('Only applicable with --cov. Merge any previous '
+ 'coverage database directory with the new '
+ 'coverage database.'))
+
+ covg.add_argument("--cov-analyze",
+ action='store_true',
+ help=('Rather than building or running any tests, '
+ 'analyze the coverage from the last run.'))
+
+ pubg = parser.add_argument_group('Generating and publishing results')
+
+ pubg.add_argument("--map-full-testplan",
+ action='store_true',
+ help=("Show complete testplan annotated results "
+ "at the end."))
+
+ pubg.add_argument("--publish",
+ action='store_true',
+ help="Publish results to reports.opentitan.org.")
+
+ dvg = parser.add_argument_group('Controlling DVSim itself')
+
+ dvg.add_argument("--print-interval", "-pi",
+ type=int,
+ default=10,
+ metavar="N",
+ help="Print status every N seconds.")
+
+ dvg.add_argument("--verbose",
+ nargs="?",
+ choices=['default', 'debug'],
+ default=None,
+ const="default",
+ metavar="D",
+ help=('With no argument, print verbose dvsim tool '
+ 'messages. With --verbose=debug, the volume of '
+ 'messages is even higher.'))
+
+ dvg.add_argument("--dry-run", "-n",
+ action='store_true',
+ help=("Print dvsim tool messages but don't actually "
+ "run any command"))
+
+ return parser.parse_args()
+
+
+def main():
+ args = parse_args()
+
+ # We want the --list argument to default to "all categories", but allow
+ # filtering. If args.list is None, then --list wasn't supplied. If it is
+ # [], then --list was supplied with no further arguments and we want to
+ # list all categories.
+ if args.list == []:
+ args.list = _LIST_CATEGORIES
if args.version:
print(version)