| # SystemVerilog Formatter | |
| <!--* | |
| freshness: { owner: 'hzeller' reviewed: '2020-10-07' } | |
| *--> | |
| `verible-verilog-format` is the SystemVerilog formatter tool. You can can | |
| get a full set of avilable flags using the `--helpfull` flag. | |
| For automatic formatting suggestions on github pull requests, there is a | |
| [easy to integrate github action available][github-format-action]. | |
| ## Usage | |
| ``` | |
| usage: verible-verilog-format [options] <file> [<file...>] | |
| To pipe from stdin, use '-' as <file>. | |
| Flags from common/formatting/basic_format_style_init.cc: | |
| --column_limit (Target line length limit to stay under when formatting.); | |
| default: 100; | |
| --indentation_spaces (Each indentation level adds this many spaces.); | |
| default: 2; | |
| --line_break_penalty (Penalty added to solution for each introduced line | |
| break.); default: 2; | |
| --over_column_limit_penalty (For penalty minimization, this represents the | |
| baseline penalty value of exceeding the column limit. Additional penalty | |
| of 1 is incurred for each character over this limit); default: 100; | |
| --wrap_spaces (Each wrap level adds this many spaces. This applies when the | |
| first element after an open-group section is wrapped. Otherwise, the | |
| indentation level is set to the column position of the open-group | |
| operator.); default: 4; | |
| Flags from verilog/formatting/format_style_init.cc: | |
| --assignment_statement_alignment (Format various assignments: | |
| {align,flush-left,preserve,infer}); default: infer; | |
| --case_items_alignment (Format case items: | |
| {align,flush-left,preserve,infer}); default: infer; | |
| --class_member_variable_alignment (Format class member variables: | |
| {align,flush-left,preserve,infer}); default: infer; | |
| --compact_indexing_and_selections (Use compact binary expressions inside | |
| indexing / bit selection operators); default: true; | |
| --distribution_items_alignment (Aligh distribution items: | |
| {align,flush-left,preserve,infer}); default: infer; | |
| --enum_assignment_statement_alignment (Format assignments with enums: | |
| {align,flush-left,preserve,infer}); default: infer; | |
| --expand_coverpoints (If true, always expand coverpoints.); default: false; | |
| --formal_parameters_alignment (Format formal parameters: | |
| {align,flush-left,preserve,infer}); default: infer; | |
| --formal_parameters_indentation (Indent formal parameters: {indent,wrap}); | |
| default: wrap; | |
| --module_net_variable_alignment (Format net/variable declarations: | |
| {align,flush-left,preserve,infer}); default: infer; | |
| --named_parameter_alignment (Format named actual parameters: | |
| {align,flush-left,preserve,infer}); default: infer; | |
| --named_parameter_indentation (Indent named parameter assignments: | |
| {indent,wrap}); default: wrap; | |
| --named_port_alignment (Format named port connections: | |
| {align,flush-left,preserve,infer}); default: infer; | |
| --named_port_indentation (Indent named port connections: {indent,wrap}); | |
| default: wrap; | |
| --port_declarations_alignment (Format port declarations: | |
| {align,flush-left,preserve,infer}); default: infer; | |
| --port_declarations_indentation (Indent port declarations: {indent,wrap}); | |
| default: wrap; | |
| --port_declarations_right_align_packed_dimensions (If true, packed | |
| dimensions in contexts with enabled alignment are aligned to the right.); | |
| default: false; | |
| --port_declarations_right_align_unpacked_dimensions (If true, unpacked | |
| dimensions in contexts with enabled alignment are aligned to the right.); | |
| default: false; | |
| --struct_union_members_alignment (Format struct/union members: | |
| {align,flush-left,preserve,infer}); default: infer; | |
| --try_wrap_long_lines (If true, let the formatter attempt to optimize line | |
| wrapping decisions where wrapping is needed, else leave them unformatted. | |
| This is a short-term measure to reduce risk-of-harm.); default: false; | |
| Flags from verilog/tools/formatter/verilog_format.cc: | |
| --failsafe_success (If true, always exit with 0 status, even if there were | |
| input errors or internal errors. In all error conditions, the original | |
| text is always preserved. This is useful in deploying services where | |
| fail-safe behaviors should be considered a success.); default: true; | |
| --inplace (If true, overwrite the input file on successful conditions.); | |
| default: false; | |
| --lines (Specific lines to format, 1-based, comma-separated, inclusive N-M | |
| ranges, N is short for N-N. By default, left unspecified, all lines are | |
| enabled for formatting. (repeatable, cumulative)); default: ; | |
| --max_search_states (Limits the number of search states explored during line | |
| wrap optimization.); default: 100000; | |
| --show_equally_optimal_wrappings (If true, print when multiple optimal | |
| solutions are found (stderr), but continue to operate normally.); | |
| default: false; | |
| --show_inter_token_info (If true, along with show_token_partition_tree, | |
| include inter-token information such as spacing and break penalties.); | |
| default: false; | |
| --show_largest_token_partitions (If > 0, print token partitioning and then | |
| exit without formatting output.); default: 0; | |
| --show_token_partition_tree (If true, print diagnostics after token | |
| partitioning and then exit without formatting output.); default: false; | |
| --stdin_name (When using '-' to read from stdin, this gives an alternate | |
| name for diagnostic purposes. Otherwise this is ignored.); | |
| default: "<stdin>"; | |
| --verbose (Be more verbose.); default: false; | |
| --verify_convergence (If true, and not incrementally formatting with | |
| --lines, verify that re-formatting the formatted output yields no further | |
| changes, i.e. formatting is convergent.); default: true; | |
| ``` | |
| ## Disabling Formatting {#disable-formatting} | |
| When you want to exempt a range of text from formatting, write: | |
| ``` | |
| // verilog_format: off | |
| ... untouched code ... | |
| // verilog_format: on | |
| ``` | |
| or | |
| ``` | |
| /* verilog_format: off */ | |
| ... untouched code ... | |
| /* verilog_format: on */ | |
| ``` | |
| As a good practice, include a reason why you choose to disable a section. | |
| ``` | |
| // verilog_format: off // my alignment is prettier than the tool's | |
| // verilog_format: off // issue #N: working around. | |
| ``` | |
| These directives take precedence over `--lines` specifications. | |
| ## Formatting included files | |
| For files that are included as snippets in other contexts, e.g. only statements, | |
| or only module body items, adding a | |
| [parsing mode directive](../../analysis#alternative-parsing-modes) (such as `// | |
| verilog_syntax: parse-as-module-body`) will let the formatter parse and format | |
| such files successfully. | |
| ## Interactive Formatting | |
| The formatter is ever a work-in-progress and may not always behave the way a | |
| user would like it to behave. If you wish to review changes introduced by the | |
| formatter and apply them interactively, we've provided a helper script (that is | |
| actually formatter-agnostic) for the job. | |
| ``` | |
| verible-transform-interactive.sh -- verible-verilog-format -- files... | |
| ``` | |
| This will run the formatter on the affected files without modifying them | |
| initially, and pass the `diff`-generated patch into a tool | |
| (`verible-patch-tool`) that interactively applies patch hunks. | |
| Answer the \[y/n\] prompts. | |
| The original files will be modified in-place with the elected changes. | |
| For convenience, one could create an alias like: | |
| ``` | |
| alias verilog-format-interactive='verible-transform-interactive.sh -- verible-verilog-format --' | |
| ``` | |
| ## Incremental Formatting | |
| If you wish to format only changed lines (a.k.a. incremental or partial | |
| formatting), the following tools are provided to assist. | |
| ### Git users | |
| `git-verible-verilog-format.sh` (installed along with `verible-verilog-format`) | |
| can be run from within any subdirectory of a Git project. It automatically | |
| detects new and changed lines, and generates the `--lines` flag for each | |
| modified file in your workspace. | |
| From `--help`: | |
| ``` | |
| git-verible-verilog-format.sh: | |
| Performs incremental file formatting (verible-verilog-format) based on current diffs. | |
| New files explicitly git-add-ed by the user are wholly formatted. | |
| Actions: | |
| 1) Runs 'git add -u' to stage currently modified files to the index. | |
| To format new files (wholly), 'git add' those before calling this script. | |
| 2) Runs 'git diff -u --cached' to generate a unified diff. | |
| 3) Diff is scanned to determine added or modified lines in each file. | |
| 4) Invokes 'verible-verilog-format --inplace' on all touched or new Verilog files, | |
| but does not 'git add' so that the changes may be examined and tested. | |
| Formatting can be easily undone with: | |
| 'git diff | git apply --reverse -'. | |
| usage: git-verible-verilog-format.sh [script options] [-- [verilog_format options]] | |
| (no positional arguments) | |
| Run from anywhere inside a git project tree. | |
| script options: (options with arguments can be: --flag=VALUE or --flag VALUE) | |
| --help | -h : print help and exit | |
| --verbose | -v : execute verbosely | |
| --dry-run : stop before running formatter, and print formatting commands | |
| --formatter TOOL : path to verilog_format binary | |
| [using: /usr/local/bin/verible-verilog-format] | |
| -- : stops option processing, and forwards remaining args as flags to the | |
| underlying --formatter tool. | |
| ``` | |
| ## Incremental Interactive Formatting | |
| In your locally modified client (p4, git) run: | |
| ```shell | |
| verible-verilog-format-changed-lines-interactive.sh | |
| ``` | |
| and follow the prompts. | |
| > NOTE: git and hg users can pass in a different base revision to diff against: | |
| > | |
| > ```shell | |
| > # Diff against the previous revision in hg | |
| > verible-verilog-format-changed-lines-interactive.sh --rev .^ | |
| > # Diff against upstream mainline in git | |
| > verible-verilog-format-changed-lines-interactive.sh --rev origin/main | |
| > ``` | |
| ## Aligned Formatting | |
| There are several sections of code that are eligible for aligned formatting. In | |
| each of these contexts, the user has some control over the alignment behavior. | |
| Without alignment, the default behavior is to flush-left, which respects | |
| indentation and minimum inter-token spacing constraints. | |
| Yet, alignment is not always desired. So how does the formatter know whether or | |
| not the user intended for alignment? It can only examine the original code and | |
| make some judgment. | |
| Consider the following example (module formal parameters): | |
| ``` | |
| module m #( | |
| int W, | |
| type T | |
| ); | |
| ... | |
| endmodule | |
| ``` | |
| With alignment, this formats to: | |
| ``` | |
| module m #( | |
| int W, | |
| type T | |
| ); | |
| ... | |
| endmodule | |
| ``` | |
| When the spacing difference between between aligned and flushed-left formatting | |
| is "sufficiently small", the formatter will align because the small difference | |
| has low risk of compromising readability. | |
| In contrast, aligning the following example _could_ be considered less readable. | |
| original: | |
| ```systemverilog | |
| module m #( | |
| int W, | |
| some_long_name T | |
| ); | |
| ... | |
| endmodule | |
| ``` | |
| aligned: | |
| ```systemverilog | |
| module m #( | |
| int W, | |
| some_long_name T | |
| ); | |
| ... | |
| endmodule | |
| ``` | |
| To detect the above condition, the formatter examines the number of _excess_ | |
| spaces (spacing errors) within an alignment group (original vs. flushed-left). | |
| If that value is lower than a threshold, the formatter infers that the author | |
| intended flush-left formatting. | |
| To induce alignment, the author needs to _inject_ four excess spaces _between_ | |
| any two tokens in any row in the aligned section, not before first tokens (which | |
| fall under indentation, not alignment). In this example, spaces are deliberately | |
| injected before `W` (but after `W` would work too): | |
| ```systemverilog | |
| module m #( | |
| int W, | |
| some_long_name T | |
| ); | |
| ... | |
| endmodule | |
| ``` | |
| formatted with alignment: | |
| ``` | |
| module m #( | |
| int W, | |
| some_long_name T | |
| ); | |
| ... | |
| endmodule | |
| ``` | |
| This also implies that previously aligned code will most likely remain aligned. | |
| Finally, if none of the above conditions hold, the formatter will leave the | |
| original code as-is, preserving all pre-existing spaces. | |
| ## Failsafe Behavior | |
| _A formatter must not corrupt data._ | |
| On rare conditions, you may observe that the formatter leaves the original code | |
| untouched. You may have encountered a fail-safe condition, in which the | |
| formatter conservatively gives up to keep your code from being corrupted. This | |
| can happen for one of several reasons. | |
| ### Syntax Errors | |
| On failure to lex/parse, the formatter gives up because it doesn't have a syntax | |
| tree to work with. | |
| ### Internal Verification | |
| Before outputting the formatted result, several properties are checked: | |
| * **Equivalence**: The output is lexically equivalent to the input, meaning | |
| that only whitespaces may have changed, but all other tokens are equal. For | |
| example, if two identifiers accidentally got merged together into one (by | |
| removing spaces between them), this check would fail. Lexical equivalence | |
| also implies that the output is still parseable. | |
| * **Convergence**: Re-formatting the _output_ results in no further changes. | |
| This property is particularly important when the formatter is used to | |
| _check_ that a file is formatted properly. Without convergence, such a check | |
| would fail after formatting, potentially asking the user to run formatting | |
| two or more times. Note that this requirement is stricter than _eventual | |
| convergence_, which allows multiple iterations before reaching a | |
| fixed-point. | |
| ### Internal Limits | |
| If an optimization such as line-wrapping optimization fails to complete within | |
| time resource limits, then the formatter also gives up to avoid hanging. | |
| ### Fatal Error | |
| If the formatter crashes for any other reason, it will leave the original file | |
| intact. The formatter does not attempt to open any file for writing in-place | |
| until all formatting calculations have been done and internal verifications | |
| pass. | |
| [github-format-action]: https://github.com/chipsalliance/verible-formatter-action |