Git Product home page Git Product logo

svlint's Introduction

svlint

SystemVerilog linter compliant with IEEE1800-2017. Written in Rust, based on sv-parser. Svlint is also integrated with most text editors via svls.

Actions Status codecov

Crates.io svlint

svlint

Installation

svlint can be installed in several ways:

  • Download a release, extract, and add the bin/ directory to your $PATH. A PDF copy of the MANUAL is included in the doc/ directory.
  • If you have a Rust toolchain, then you can install the binary with cargo, via cargo install svlint. This will copy the svlint binary (and the dev-only mdgen binary) to (usually) ~/.cargo/bin, but not the wrapper scripts (e.g. svlint-parseonly) or pre-written configurations (e.g. parseonly.toml) from rulesets/.
  • snapcraft, via sudo snap install svlint.

Usage

To see information about the command line interface use svlint --help, and to see which version you're running use svlint --version.

Further information on how svlint works, how to configure it, and other usage information is in the manual.

svlint's People

Contributors

5han7anu-s avatar akberg avatar dalance avatar davemcewan avatar dependabot-preview[bot] avatar dependabot[bot] avatar dpretet avatar raamakrishnan avatar remes-codasip avatar ronitnallagatla avatar shrechinno avatar skjdbg avatar so298 avatar supleed2 avatar taichi-ishitani avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

svlint's Issues

Reports errors when file list includs empty lines

The svlint reports errors when input file list includes empty lines.
You can reproduce this issue by using the attached sample code.
svlint.zip

Unzip the attached zip file and invoke command below.

$ svlint -f list.f -v

Then you will see the error message below.

$ svlint -f list.f -v
Info: pass 'foo.sv'
Error: File error: ""
Info: pass 'bar.sv'
Error: File error: ""

I think the tool should ignore empty lines.

Error when using both of filelist and source file

I got an error when using both of filelist and source file.

use_both_of_filelist_and_source_file.tar.gz

I attached a test case. You can reproduce this error by using this:

$ tar -xvf use_both_of_filelist_and_source_file.tar.gz
$ cd use_both_of_filelist_and_source_file
$ svlint -f list.f foo.sv

Then you will see the following error.

Config file '.svlint.toml' is not found. Enable all rules
Error: File error: "module foo;"
Error: File error: "endmodule"

Compact array definition causes error

When I svlint my code using this command:

svlint -c ../../.svlint.toml poly1305.sv

(With or without the -c option)

I get this error:

Error: parse error
   --> poly1305.sv:14:2
   |
14 | 	input		logic		i_clk,
   |  ^

This is the code, when I change the compact array to the verbose (x:0) it works fine.

(
	input		logic		i_clk,
					i_rst,
					i_init,

	input		logic[16][P_BYTE_SIZE]	i_msg,
	input		logic[32][P_BYTE_SIZE]	i_key,
	input		logic[32]		i_size,
	output 		logic[32][P_BYTE_SIZE]	o_mac
);
(
	input		logic		i_clk,
					i_rst,
					i_init,

	input		logic[15:0][P_BYTE_SIZE-1:0]	i_msg,
	input		logic[31:0][P_BYTE_SIZE-1:0]	i_key,
	input		logic[31:0]			i_size,
	output 		logic[31:0][P_BYTE_SIZE-1:0]	o_mac
);

I installed svlint using "cargo install svlint" and svls using "cargo install svls", same issue on both.

Suggestion: Filelist supports environment variables without any parentheses

Thank you for creating such a great Linter tool !

I'd like to make a suggestion. Can you support environment variables without parentheses?
Like this format:

$XXX_DIR/yyy.sv

This format comes up so often in my projects that I can't fix them all

I think this is an easy change and would like to update the code to support it
Thank you again for your work

Index error when printing default_nettype_none on file with empty first line

svlint --filelist top_filelist.vc, where top_filelist.vc is my simple filelist, containing ran with the following output:

Fail: default_nettype_none
   --> ./rtl_modules/constants.svh:2:0
  |
thread 'main' panicked at 'slice index starts at 1 but ends at 0', /home/andreas/.cargo/registry/src/github.com-1ecc6299db9ec823/svlint-0.4.18/src/printer.rs:248:46
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
2 |

Seems beg is 1 and next_crlf is 0. Looking into the rule, default_nettype_none I understand that the linter panics on printing the erroneous code, but for this rule the error is exactly that there is no code on the expected line. Empty line is a special case that doesn't seem to be handled in the printer::Printer::with_pos function, column (=2) ends up being larger than the row's line length.

I would suggest either printing it as row:col 0:0, or pointing to the first non-empty line (might be more readable/informative)

Content of constants.svh, if it helps:

// Define system wide constants

`ifndef CLK_FRQ
`define CLK_FRQ 100_000_000
`endif

`ifndef N_OSCILLATORS
`define N_OSCILLATORS 16
`endif

`ifndef ENVELOPE_LEN
`define ENVELOPE_LEN 8
`endif

`ifndef SAMPLE_RATE
`define SAMPLE_RATE 44100
`endif

`ifndef SPI_WIDTH
`define SPI_WIDTH 8
`endif

`input must have var` clarification

If you follow the (good IMO) svlint recommendation to use default nettype none and then add the required vars to module ports you might end up with code like this:

`default_nettype none

module foo (
  input var logic i_a,
  output var logic o_b
);

svlint is happy with that. However the default net type for input ports is actually wire, not var. If you put input wire (or input tri) then svlint says you should use input var.

I'm not an SV pro - is there actually any difference between wire and var here, and what's wrong with using wire?

New Rule: Parameter Must Have Default Value

We have been having some really weird issues with Vivado where its source scanner (srcscanner.exe or srcscanner on Linux) process will crash with no log file and return "[filemgmt 56-315] Source scanning failed during design analysis. To get more details run synthesis or simulation and check the log.". This happens in two different somewhat recent versions of Vivado. Running synthesis will report that some files are missing but no further info. Looking more closely at the Sources -> Hierarchy tab of Vivado we noticed some of our modules have instances names that match some of our parameters instead of modules, we concluded that somehow maybe the srcscanner's internal data structures were being corrupted, after many days changing a lot of stuff across our code base to figure out what was going on we have a handful of rule suggestions to make.

One of the things we did that seemed to help the problem was give every module and interface parameter a default value.

Example

// ALLOWED
module example_module #(
    parameter int CLOCK_FREQ = 1000
) (
    input clk
);

// NOT ALLOWED
module example_module #(
    parameter int CLOCK_FREQ
) (
    input clk
);

A somewhat related but different issue seems to be documented in Xilinx's answer records, https://support.xilinx.com/s/article/69846?language=en_US

Regardless of if this is the real problem, its probably a handy rule to have anyways.

New Rule: Check that module is hierarchy-only.

  • Fail on use of any operator outside of constant expressions.
  • Useful to confirm that a module is a fully synthesized netlist.
  • Useful to confirm that a module is only connecting (separately synthesized) sub-modules.

Per File and Per Line Lint Rule Disable

We are running into some issues where we have a few cases where we want to violate the lint rules we enabled but don't want to disable the lint rule for the whole file. Linting tools for other languages have a way to disable lint rules on an individual basis for a whole file or on a per line/per statement basis.

Something similar to how PyLint does things
# pylint: disable=line-too-long,multiple-statements

I think something like the following would work for SVLint.

// svlint: file_disable=non_blocking_assignment_in_always_comb

if (value) a <= b; // svlint: disable=if_with_begin

Cannot ignore `include statements

Is there a way to tell svlint to ignore `include statements? This can be a really useful single-file linter, but it fails if the -i switch isn't provided, and some of my include files are in quite strange paths. Ideally, the tool would simply ignore these, and parse the file without them, treating any unknown functions/modules/interfaces/parameters as 'unknown', verifying the syntax only.

Bug: `parameter_type_twostate` doesn't catch 4-state type when `parameter` keyword is omitted.

When parameter keyword is omitted, subsequent parameters are in a list_of_param_assignments.

module M
  #(int A = 0
  , integer B = 0
  ) ();
endmodule
  • Current behavior: Check only the first param assignment.
  • Intended behavior: Check all param assignments in the list.
  • Likely similar bugs in parameter_explicit_type, localparam_type_twostate, and localparam_explicit_type.
  • See parameter_default_value for list-processing logic.

prefix_module incorrectly identifies an interface instance

As the title says, the prefix_module rule incorrectly identifies an interface instantiation as a module instantiation and it results in an incorrect warning produced by the rule.
I know it's not trivial to identify an interface instantiation without finding the interface definition but I'll open an issue regardless.
I thought that the issue was more suitable for this project as opposed to sv-parser as modifying the rule seems like an easier way.
Example:

ifc_interface interface_instance(); //`module` name must have prefix "mod_"svls(prefix_module)

New rule suggestion

I would like to see a new rule added to enforce including `default_nettype none at (near) the top of every module. This directive forces that every declaration must explicitly define the nettype rather than rely on the implicit rules set up in the language. The reason this is important is because it is a common mistake to have typographical errors in references to signal names. The default rules in the language will treat the reference to a non existent variable as an implicit declaration of a new variable with the default net type (typically wire) and will not yield an immediate compile time error - it can be detected only with careful simulation and testing. Whereas, including the suggested directive in the module will force an immediate compile time error since the implicit declaration of a new variable (due to typo) will not have a default netttype (i.e., none) and cannot be referenced. Warning: using this lint rule on code that leverages implicit net type wire (e.g. input x) will generate a lot of nuisance lint warnings until implicit nettype declarations are converted to explicit nettype declarations (e.g., input wire x).

Some Rules Cause TOML Compilation to Fail

I'm working on setting up a default .svlint.toml file for my company. There's a few rules that we wanted to disable for our own coding standards, so it appears that the only option is to create the toml file and specify all the rules we want to turn on using <rule> = true.

Here is my current toml file:

[rules]
blocking_assignment_in_always_ff = true
case_default = true
default_nettype_none = true
enum_with_type = true
# explicit_case_default = true
# explicit_if_else = true
for_with_begin = true
function_same_as_system_function = true
function_with_automatic = true
generate_case_with_label = true
generate_for_with_label = true
generate_if_with_label = true
generate_keyword_forbidden = true
generate_keyword_required = true
genvar_declaration_in_loop = true
genvar_declaration_out_loop = true
if_with_begin = true
inout_with_tri = true
input_with_var = true
interface_port_with_modport = true
legacy_always = true
level_sensitive_always = true
# localparam_explicit_type = true
# localparam_type_twostate = true
loop_variable_declaration = true
lowercamelcase_interface = true
lowercamelcase_module = false
lowercamelcase_package = false
non_ansi_module = true
non_blocking_assignment_in_always_comb = true
output_with_var = true
# parameter_explicit_type = true
parameter_in_package = true
# parameter_type_twostate = true
prefix_module = true
prefix_package = false
priority_keyword = true
# sequential_block_in_always_comb = true
# sequential_block_in_always_ff = false
# sequential_block_in_always_latch = false
tab_character = true
unique0_keyword = true
unique_keyword = true
uppercamelcase_package = true
uppercamelcase_module = false
wire_reg = true

All of the rules which I've commented out (#) cause the compilation to fail if I include them. It doesn't matter if they're true or false. I get the following error: Failed to parse d:\<path>\.svlint.toml. Enable all lint rules.. Is there anything I'm doing wrong for these rules, or is this a bug?

I am using the VSCode plugin.

Cannot add defines with values

It appears that -dDEFINE can only add an empty-valued macro. Is there a way to pass a value to the linter, for instance by using -dDEFINE=5?

New Rule: Monadic behaviour should not be specified inside assertion action blocks.

Detect non-sensical cases like this:

assert (foo) begin: pass_action_block
  $display("IO says it passed"); // Usually replace with $info.
end: pass_action_block
else begin: fail_action_block
  $display("IO says it failed"); // Usually replace with $error, or perhaps $fatal, $warning, $info.
  a++; // Undefined behaviour...
  b--; // ...but will probably work in single-threaded sim.
end: fail_action_block

Suggestion for legacy always not to force always_ff

In FPGA designs you can use an initial block to set the startup value for a FF. However, VCS complains if you use an always_ff on the same signal that it's multiply driven. ex:

initial begin
out_sig = '0;
end
always_ff @(posedge clk) out_sig <= in_sig;

would produce a multiply driven net error.

Question regarding sequential_block_in_always_ff

Hello, I tarted using svlint in order to improve the quality of the RTL I write and keep all my code consistent overall, I also use svlint to check if there is any syntax error, I find that faster then calling a commercial EDA compiler/simulator.

I'm the kind of guy who uses begin/end inside my always_ff construct, however svlint seems to not like it, I know I can disable the check but I'm curious to know what kind of problem can occur while using begin/end within always_ff construct.
The tool hint log state the following:

hint : begin/end forbidden within always_ff constuct
reason: prevent introducing sequential dependencies.

Can someone explain me what does it mean ?

Thanks,
Mass.

Unexpected include error

I got an unexpected include error when linting SV file which has a macro call of which an argument is another macro like below.

`define PATH_BAR  bar.sv
`define QUATE(path) `"path`"
`include  `QUATE(`PATH_BAR)

unexpected_include_error.tar.gz

I attached a sample test case. You can use reproduce this error by using this:

$ tar -xvf unexpected_include_error.tar.gz
$ cd unexpected_include_error
$ svlint foo.sv

Then you will see the error message below.

Config file '.svlint.toml' is not found. Enable all rules
Error: failed to include '`PATH_BAR'

Rule `explicit_if_else` only warns the first time in each `always_*` block

The same behaviour was observed with both

  • svlint "0.5.5 ( rev: 0aa25c3, rustc: 1.62.0, build at: 2022/07/06 00:34:49 )"
  • svls "0.2.4 ( rev: 9586d6c, rustc: 1.62.0, build at: 2022/07/06 03:26:29 )"

I have made a few test cases to show what I mean:

module test_fine1;
  logic ck, a, b, c, d;
  always_ff @(ck)
    if (a) // GOOD: warns here
      b <= c;
  always_ff @(ck)
    if (b) // GOOD: warns here
      c <= d;
endmodule

module test_fine2;
  logic ck, a, b, c, d;
  always_ff @(ck) begin
    if (a)
      b <= c;
    else
      b <= d;
  end
  always_ff @(ck)
    if (b) // GOOD: warns here
      c <= d;
endmodule

module test_notfine1;
  logic ck, a, b, c, d;
  always_ff @(ck) begin
    if (a) // GOOD: warns here
      b <= c;
    if (b) // BAD: DOES NOT warn here
      c <= d;
  end
endmodule

module test_notfine2;
  logic ck, a, b, c, d;
  always_ff @(ck) begin
    if (a)
      b <= c;
    else
      b <= d;
    if (b)  // BAD: DOES NOT warn here
      c <= d;
  end
endmodule

I'm not sure if the issue of only applying once is important for / affects other rules.

Add option to force color output

In some CI environments for example GitLab-CI with docker containers makes svlint think that it cannot use colored output, when in fact it is possible.

Is it possible to add this option for svlint?

Solved my issue when reading colored documentation. You need to add the environment variable CLICOLOR_FORCE = 1.

Unexpected parse error on casting

I got an unexpected parse error on width casting.
You can re-produce the same error by using following code.

package test_pkg;
  typedef struct packed {
    int width;
  } test_struct;
endpackage

module test_module
  import  test_pkg::*;
#(
  parameter test_struct TEST_PARAM  = '0
);
  logic [TEST_PARAM.width-1:0]  test;

  always_comb begin
    test  = TEST_PARAM.width'(0);
  end
/*
  localparam  int WIDTH = TEST_PARAM.width;
  always_comb begin
    test  = WIDTH'(0);
  end
*/
endmodule
$ svlint  test.sv 
Config file '.svlint.toml' is not found. Enable all rules
Error: parse error
   --> test.sv:14:3
   |
14 |   always_comb begin
   |   ^

I changed TEST_PARAM.WIDTH to WIDTH then I saw no error.

I think TEST_PARAM.width'(0) should be accepted by following rules.

  • cast ::= casting_type ' ( expression )
  • casting_type ::= constant_primary
  • constant_primary ::= ps_parameter_identifier constant_select
  • constant_select ::= [ { . member_identifier constant_bit_select } . member_identifier ]constant_bit_select[ [ constant_part_select_range ] ]

All class scoped variables should have a prefix of "m_"

All class member variables should begin with "m_". Conversely, if a variable begins with "m_", it should be a class scoped variable and not a method scoped variable

Pass

class abc extends uvm_sequence_item;
   int m_foo;
   string m_bar;

   function void dont_care();
     int foo;
     int bar;
   endfunction: dont_care
endclass: abc

Fail

class abc extends uvm_sequence_item;
  int m_foo;
  string bar;                               // Class scoped variable doesn't begin with "m_"
  
  function void dont_care();
    int m_foo;                              // Non-class (local) variable begins with "m_"
    int bar;
  endfunction: dont_care
endclass: abc

function_with_automatic check does not consider default lifetime

Problem

The default lifetime can be specified in module/interface/package/etc header definition.
However it's seemed that function_with_automatic does consider default lifetime.

Expectation

interface automatic test_if;
  function void test_func();
  endfunction
endinterface

function_with_automatic checker should not be failed because test_func is automatic function.

Actual

function_with_automatic checker reports following error.

Fail: function_with_automatic
   --> test.sv:2:3
  |
2 |   function void test_func();
  |   ^^^^^^^^ hint  : `function` must be `automatic`
  |            reason: this causes mismatch between simulaton and synthesis

Making dot-f parser into its own crate

Hi

Thank you for this wonderful set of projects. Your project made me to learn rust, just because I wanted to contribute to it.

I think it would be helpful if the dot-f file parser is made into its own crate. This crate can be used by svls (to provide better workspace-level features) and any other future projects that make use of sv-parser or svlint.

Timescale with `define macros

Thanks for the awesome work on this project and sv-parser! Just ran across a small issue when using `timescale in combination with `define macros. I'm not sure about what the LRM says about this syntax, but it seems to be supported by some commercial and open-source simulators.

Example:

`define TIME_UNIT 1ns
`define TIME_PRECISION 1ps
`timescale `TIME_UNIT / `TIME_PRECISION
module test;
    initial begin
        #(1.234321ns);
        $display($realtime);
        $finish;
    end
endmodule

Output:

> svlint test.sv
Config file '.svlint.toml' is not found. Enable all rules
Error: parse error
   --> test.sv:3:1
  |
3 | `timescale `TIME_UNIT / `TIME_PRECISION
  | ^

Error when parsing UVM macros

I'm not sure whether I should be filing this against svlint or svparse, but since I'm the issue I'm having is hit when using svlint, I decided to file it here.

I have a minimal testbench that, when using UVM macros, hits the following parse error:

$ svlint --config .svlint.tom -f sample.vc -i ../1800.2-2017-1.0/src
Error: parse error
   --> ../1800.2-2017-1.0/src/macros/uvm_object_defines.svh:296:5
    |
296 |   `m_uvm_object_registry_internal(T,T)  \
    |     ^

You can reproduce this locally by downloading the attached files and calling:

make UVM_HOME=<your local UVM install>

repro.tar.gz

New rule: Unconnected pin

Some simulators (xvlog/xsim at least) allow building module instantiations with missing pins, would be nice to catch!

Example

// my_mod.sv
module my_mod (input a, input b, output c, output d);
  /* do stuff */
endmodule
// top.sv
module top;
  logic ain, cout;
  my_mod m0 (.a(ain), .c(cout));
endmodule

A good error message could be

Fail: unconnected_pin
   --> /path/to/project/top.sv:3:3
   |
3  |    my_mod m0 (.a(ain), .c(cout));
   |    ^^^^^^ hint: module instantiation is missing pins: b, d
   |           reason: unconnected pins give unpredictable values

One-line flag doesn't work with errors

Hi,

Your linter/parser are the only tools currently out there that can parse verilog/systemverilog files without doing full hierarchy elaboration, parsing includes, modules, parameter value etc. This makes it very suitable for a real-time syntax parser/linter, to be used with text editors such as Sublime, emacs, or in my case - vim. I'm currently writing a vim parser file for ALE (https://github.com/dense-analysis/ale), and with the latest version of svlint (0.3.1) - it works! Thank you for this tool - its really fast and looks like it supports every language construct.

One inconvenience in the current version of svlint is that the "-1" flag only applies to warnings. These are reported as

Fail testcase10.v:47:9 input wire CLK, hint: input must have var

Errors, on the other hand, are never condensed into one line:

Error: parse error
--> testcase10.v:10:5
|
10 | delay_line_10
| ^

Currently, I'm passing the above outcome through sed, and doing some regex magic to condense it into one line. Is is possible to make the "-1" argument apply to errors as well? The expected output should be something like:

Error testcase10.v:10:5 delay_line_10, hint: parse error: error description if exists

This will make using the tool's output as a syntax/linter so much easier

Thank you,
Greg

parse error on sequential casting

I got an error during parsing source file including sequential casting.
You can reproduce this error by using this code.

module top;
  int a = 17'(1+2)'(1+2);
endmodule
Error: parse error
   --> test.sv:2:19
  |
2 |   int a = 17'(1+2)'(1+2);
  |                   ^

I think this should be accepted according to following rules.

  • constant_cast ::= casting_type ' ( constant_expression )
  • casting_type ::= simple_type | constant_primary | signing | string | const
  • constant_primary ::= constant_cast

In addition, commercial simulators, e.g. VCS, Xcelium, allows the above code.

  • svlint version
    • 0.4.17

Incorrect variable name parsing when using prefix_output

The following example gets parsed correctly as expected and the prefix_output rule succeeds:

module test(output logic [7:0] o_test);

but when a parameter identifier is used instead of the numbers in the width specifier like in the example down below:

module test(output logic [PARAM_VAL-1:0] o_test);
parameter PARAM_VAL= 8;

It assumes that the variable's name is PARAM_VAL and the prefix_output rule results in a warning.
I guess this issue applies to the prefix_input and prefix_inout as well but I haven't checked them.

misspelling "tab_charactor"

Hi
Just a tiny problem. The sample configuration generated by svlint --example has a misspelling -- "tab_charactor".
Supposed to be "tab_character"?
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.