The verible-verilog-lint
SV style linter analyzes code for patterns and constructs that are deemed undesirable according to the implemented lint rules. Ideally, each lint rule should reference a passage from an authoritative style guide. The style linter operates on single unpreprocessed files in isolation.
For automatic code-reviews on github, there is a easy to integrate github action available.
The style linter excels at:
Consequences of reading unpreprocessed input:
Currrent limitations:
Style lint rule development guide.
usage: verible-verilog-lint [options] <file> [<file>...] Flags from external/com_google_absl/absl/flags/parse.cc: --flagfile (comma-separated list of files to load flags from); default: ; --fromenv (comma-separated list of flags to set from the environment [use 'export FLAGS_flag1=value']); default: ; --tryfromenv (comma-separated list of flags to try to set from the environment if present); default: ; --undefok (comma-separated list of flag names that it is okay to specify on the command line even if the program does not define a flag with that name); default: ; Flags from verilog/analysis/verilog_linter.cc: --rules (Comma-separated of lint rules to enable. No prefix or a '+' prefix enables it, '-' disable it. Configuration values for each rules placed after '=' character.); default: ; --rules_config (Path to lint rules configuration file. Disables --rule_config_search if set.); default: ""; --rules_config_search (Look for lint rules configuration file '.rules.verible_lint' searching upward from the location of each analyzed file.); default: false; --ruleset ([default|all|none], the base set of rules used by linter); default: default; --waiver_files (Path to waiver config files (comma-separated). Please refer to the README file for information about its format.); default: ""; Flags from verilog/parser/verilog_parser.cc: --verilog_trace_parser (Trace verilog parser); default: false; Flags from verilog/tools/lint/verilog_lint.cc: --autofix (autofix mode; one of [no|patch-interactive|patch|inplace-interactive|inplace|generate-waiver]); default: no; --autofix_output_file (File to write a patch with autofixes to if --autofix=patch or --autofix=patch-interactive or a waiver file if --autofix=generate-waiver); default: ""; --check_syntax (If true, check for lexical and syntax errors, otherwise ignore.); default: true; --generate_markdown (If true, print the description of every rule formatted for the Markdown and exit immediately. Intended for the output to be written to a snippet of Markdown.); default: false; --help_rules ([all|<rule-name>], print the description of one rule/all rules and exit immediately.); default: ""; --lint_fatal (If true, exit nonzero if linter finds violations.); default: true; --parse_fatal (If true, exit nonzero if there are any syntax errors.); default: true; --show_diagnostic_context (prints an additional line on which the diagnostic was found,followed by a line with a position marker); default: false;
We recommend each project maintain its own configuration file for convenience and consistency among project members.
Syntax errors and lint rule findings have the following format:
FILE:LINE:COL: text...
Examples:
path/to/missing-endmodule.sv:3:1: syntax error (unexpected EOF). path/to/number-as-statement.sv:2:3: syntax error, rejected "123". path/to/bad-dimensions.sv:114:43: Packed dimension range must be in decreasing order. http://your.style/guide.html#packed-ordering [packed-dimensions-range-ordering]
User documentation for the lint rules is generated dynamically, and can be found at https://chipsalliance.github.io/verible/verilog_lint.html, or by running verible-verilog-lint --help_rules
for text or --generate_markdown
. We also provide a Bazel build rule:
# Generating documentation bazel build :lint_doc # It will be generated into bazel-bin/documentation_verible_lint_rules.md
The --rules
flag allows to enable/disable rules as well as pass configuration to rules that accept them. It accepts a comma-separated list rule names. If prefixed with a -
(minus), the rule is disabled. No prefix or a ‘+’ (plus) prefix enables the rule. An optional configuration can be passed after an =
assignment. Each name/value is
So rule configurations with parameters looks like this
--rules=[+-]rule-name="<param>:<paramvalue>;<param2>:<value>",[+-]next-rule...
The following example enables the enum-name-style
rule, enables and configures the line-length
rule (80 characters length) and disables the no-tabs
rule.
verible-verilog-lint --rules=enum-name-style,+line-length=length:80,-no-tabs ...
Some lint rules have multiple parameters, these are separated with semicolon. Since common shells treat semicolon as special character, you have to put the parameters in quotes.
verible-verilog-lint --rules="undersized-binary-literal=hex:true;lint_zero:true" ...
Additionally, the --rules_config
flag can be used to read configuration stored in a file. The syntax is the same as above, except the rules can be also separated with the newline character.
Some lint rules allow users to use a regular expression to configure the rule. Verible utilises the RE2 regular expression library and full syntax documentation can be found at https://github.com/google/re2/wiki/syntax.
verible-verilog-lint --rules="enum-name-style=style_regex:[a-z_0-9]+(_t|_e)" ...
For naming style rules, the regex can be kept simple and not have to worry about the beginning starting with a digit as this is already taken care of by the lexer/parser. Below are some common naming style regex patterns that can be used.
Naming Style | Regex Expression |
---|---|
lower_snake_case | [a-z_0-9]+ |
UPPER_SNAKE_CASE | [A-Z_0-9]+ |
Title_Snake_Case | [A-Z]+[a-z0-9]*(_[A-Z0-9]+[a-z0-9]*)* |
Sentence_snake_case | ([A-Z0-9]+[a-z0-9]*_?)([a-z0-9]*_*)* |
camelCase | ([a-z0-9]+[A-Z0-9]*)+ |
PascalCase | ([A-Z0-9]+[a-z0-9]*)+ |
In the rare circumstance where a line needs to be waived from a particular lint rule, you can use the following waiver comment:
// This example waives the line after the waiver. // verilog_lint: waive rule-name The next non-comment line like this one is waived. // This example waives the same line as the waiver. This line is waived. // verilog_lint: waive rule-name // This example shows accumulation of waivers over multiple lines. // verilog_lint: waive rule-name-1 // verilog_lint: waive rule-name-2 // Other comments, possibly waivers for other tools. This line will be waived for both rule-name-1 and rule-name-2. // This example shows how to waive an entire range of lines. // verilog_lint: waive-start rule-X ... All lines in between will be waived for rule-X ... // verilog_lint: waive-stop rule-X
If you prefer to manage waivers out-of-source, then waiver files may be a suitable option, especially if the use of multiple linters risks cluttering your source with too many lint waiver directives.
The --waiver_files
flag accepts a single configuration file or a list of files (comma-separated). Specifying multiple files is equivalent to concatenating the files in order of appearance. By default, the rules are applied to all files, but with --location
you can choose to only apply them to filenames matching the location regexp.
The format of this file is as follows:
waive --rule=rule-name-1 --line=10 waive --rule=rule-name-2 --line=5:10 waive --rule=rule-name-3 --regex="^\s*abc$" waive --rule=rule-name-4 --line=42 --location=".*some_file.*"
The --line
flag can be used to specify a single line to apply the waiver to or a line range (separated with the :
character). Additionally the --regex
flag can be used to dynamically match lines on which a given rule has to be waived. This is especially useful for projects where some of the files are auto-generated.
The name of the rule to waive is at the end of each diagnostic message in []
.
These waiver rules can be automatically generated with the AutoFix mode generate-waiver
to stdout, or to a waiver file if a path is passed to --autofix_output_file
. e.g.
verible-verilog-lint --autofix=generate-waiver --autofix_output_file=violations.waiver ...
Generated waiving rules will follow this format:
waive --rule=<rule_name> --line=<number> --location=<file_name>
Syntax errors cannot be waived. A common source of syntax errors is if the file is not a standalone Verilog program as defined by the LRM, e.g. a body snippet of a module, class, task, or function. In such cases, the parser can be directed to treat the code as a snippet by selecting a parsing mode, which looks like a comment near the top-of-file like // verilog_syntax: parse-as-module-body
.
Some trivial violations (e.g. trailing spaces or repeated semicolons) can be fixed automatically. The --autofix
flag controls the mode in which fixes are presented or applied.
--autofix value | Description |
---|---|
no | No fix is is shown or applied. |
patch-interactive | Interactive choice of fixes that are written as unified diff to --autofix_output_file . |
inplace-interactive | Interacive choice of fixes that are applied to the original file in place. (modifies input) |
patch | All available fixes are written as unified diff. |
inplace | All available fixes are applied to the original file in place. (modifies input) |
generate-waiver | Generates a waiver rule for each violation, as a temporary fix. |
If --autofix_output_file
is not given, patch or waiver output is written to stdout.
The interactive modes --autofix=patch-interactive
and --autofix=inplace-interactive
offer the following actions for each fix:
y
- apply fixn
- reject fixa
- apply this and all remaining fixes for violations of this ruled
- reject this and all remaining fixes for violations of this ruleA
- apply this and all remaining fixesD
- reject this and all remaining fixesp
- show fixP
- show fixes applied so far?
- print this help and prompt againExample interactive session (--autofix=inplace-interactive
):