Skip to content

dalance/svlint-plugin-sample

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

svlint-plugin-sample

This is a sample project of an svlint plugin. An svlint plugin implements one or more rules (either TextRule or SyntaxRule) in an externally developed project, compiling a shared object file which is dynamically loaded at svlint runtime.

Usage

Use svlint's --plugin option with the shared object produced by cargo build in this repository. The shared object can be copied from target/(debug|release)/, but the filename will be platform-dependent.

  • Linux: lib<name>.so
  • MacOS: lib<name>.dylib
  • Windows: <name>.dll
$ svlint --plugin libsvlint_plugin_sample.so test.sv
Fail: sample_plugin
   --> test.sv:2:1
  |
2 | initial begin
  | ^^^^^^^ hint  : Remove the `initial` process.
  |         reason: This example doesn't like `initial` processes.

The loaded plugin is automatically enabled, has access to values from svlint's TOML configuration, and syntax rules may be controlled using special comments.

Implementation

As a plugin must create a shared object, the crate type of Cargo.toml should be cdylib. Alternatively, dylib could be used, but the resulting binary may be very large.

[lib]
crate-type = ["cdylib"]

A plugin project must define a get_plugin function (in src/lib.rs) which returns the list of rules that it implements. Svlint provides a macro pluginrules which makes this quite simple.

#[allow(improper_ctypes_definitions)]
#[no_mangle]
pub extern "C" fn get_plugin() -> Vec<Rule> {
    pluginrules!(
        SamplePlugin,
        AnotherPlugin,
        ForbiddenRegex
    )
}

Rules are defined by the TextRule or SyntaxRule traits, see src/forbidden_regex.rs and src/another_plugin.rs for examples of each.

impl SyntaxRule for SamplePlugin {
    fn check(
        &mut self,
        _syntax_tree: &Tree,
        event: &NodeEvent,
        _config: &ConfigOption,
    ) -> SyntaxRuleResult {
        match event {
            NodeEvent::Enter(RefNode::InitialConstruct(_)) => SyntaxRuleResult::Fail,
            _ => SyntaxRuleResult::Pass,
        }
    }

    fn name(&self) -> String {
        String::from("sample_plugin")
    }

    fn hint(&self, _config: &ConfigOption) -> String {
        String::from("Remove the `initial` process.")
    }

    fn reason(&self) -> String {
        String::from("This example doesn't like `initial` processes.")
    }
}

TextRule must implement check, name, hint and reason. SyntaxRule must implement check, name, hint and reason.

Testing

This sample project includes a basic test infrastructure to test its rules. To run the tests, first build the shared object (cargo build), then run cargo test. If you wish to debug via println, run cargo test -- --show-output.

The test infrastructure has 3 main parts:

  1. The tests module in src/lib.rs.
  • so_path(): Return a string with the expected filesystem path of the shared object. If your plugin has an unusual name (specified in Cargo.toml), then this may require modification.
  • execute_linter(): Attempts to perform in the same way as svlint does. If svlint is modified, then this may require modification.
  • plugin_test(): Called by the functions written by build.rs. Should not normally require modification.
  1. A collection of SystemVerilog testcase files in testcases/(fail|pass)/. Naturally, you must create your own testcases for your own plugin rules. To add a SystemVerilog test file, simply copy it to testcases/pass/ if it must pass all of the plugin's rules, or to testcases/fail/ if it must fail any of the plugin's rules.
  2. The build script (build.rs) which uses the testcase files to produce test functions just before the main compilation.

About

A sample project of svlint plugin

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published