# BugFinder BugFinder is a Linty scan engine that provides additional rules based on synthesized code analysis. These advanced rules help you detect bugs and vulnerabilities, improving the reliability and security of your IPs. BugFinder embeds [Tabby CAD Suite](https://www.yosyshq.com/tabby-cad-datasheet) from [YosysHQ](https://www.yosyshq.com/) to synthesize your code. BugFinder is available as part of [Linty Ultra](https://linty-services.com/pricing). BugFinder rules are tagged as bug-finder. ## Usage [Activate some rules](rules_to_check) tagged as [`bug-finder`](https://demo.linty-services.com/coding_rules?tags=bug-finder), [configure BugFinder](#configuration) and [scan your code](scan.md#run-linty-scan). ## Configuration On Windows, make sure that the files listed in *.ys files match the case of the actual files on disk. Otherwise, it can lead to tricky issues. ### Read your HDL files Add a `read.ys` file to `.linty/yosys/` to tell Linty how to read the VHDL/Verilog files of your project in the right order. If your project already defines a filelist (Verilog/SystemVerilog only), the content of this `read.ys` file will be: ```bash verific -f -sv ./my_filelist.f ``` Otherwise, manually list all files. This list of files is likely already stored somewhere in a configuration file in your project, or it can be generated from your synthesis tool. We advise you to add a script to your continuous integration process to automatically convert this configuration file to the Yosys format described below. All paths in the `read.ys` file are relative to the root of your source code repository. ```bash # List all the files of your IP in the right order. # # For instance, let's say that: # - Your IP consists of two VHDL files and one Verilog/SystemVerilog file: fly.vhd, dream.v and top.vhd # - The top module is defined in top.vhd # verific -vhdl ./fly.vhd verific -sv ./dream.v verific -vhdl ./top.vhd ``` If some files should not be compiled in `work` but in a specific library: ```bash verific -work -[vhdl|sv] # Example #1: Compile 'fly.vhd' VHDL file into 'dream' library verific -work dream -vhdl ./fly.vhd # Example #2: Compile 'fly.sv' SystemVerilog file into 'dream' library verific -work dream -sv ./fly.sv ``` It's very likely that your IP uses third-party libraries. In this case, Linty will need to read interfaces with these third-party libraries: ```bash # If you get the following kind of error: # VERIFIC-ERROR [VHDL-1240] ./xxx.vhd:xxx: 'vcomponents' is not compiled in library 'xpm', # You need to add the following at the beginning of your read.ys file: verific -work xpm -vhdl ./third-party-libraries/.../xpm_VCOMP.vhd # If you get the following kind of error: # VERIFIC-ERROR [VHDL-1240] ./xxx.vhd:xxx: 'blabla' is not compiled in library 'work', # You need to add the following at the beginning of your read.ys file: verific -vhdl -lib ./third-party-libraries/.../blabla.vhd ``` If for some reason, you do not have access to these third-party libraries during the Linty scan, you can tell Linty to consider third-party components as blackboxes by adding the following to the top of the `read.ys` file: ```bash verific -set-warning VHDL-1240 ``` With this configuration, note that Linty may fail to detect some errors (such as a CDC between a third-party component and your code) as Linty knows nothing about these third-party components. See [Yosys documentation](https://yosyshq.readthedocs.io/projects/yosys/en/stable/cmd/verific.html) for more details. #### Vivado In Vivado, the following Tcl command returns the source files in compile order: ```tcl get_files -compile_order sources -used_in synthesis ``` Based on this command, the following Tcl script generates a starting `read.ys` file: ```tcl proc rel_to {base path} { set base [file normalize $base] set path [file normalize $path] set bs [file split $base] set ps [file split $path] set i 0 set n [llength $bs] set m [llength $ps] set lim [expr {$n < $m ? $n : $m}] while {$i < $lim && [lindex $bs $i] eq [lindex $ps $i]} { incr i } if {$i == 0} { return $path } set up [list] for {set k $i} {$k < $n} {incr k} { lappend up ".." } set down [lrange $ps $i end] if {[llength $up] == 0 && [llength $down] == 0} { return "." } if {[llength $up] == 0} { return [file join {*}$down] } if {[llength $down] == 0} { return [file join {*}$up] } return [file join {*}$up {*}$down] } proc vivado_to_linty {base_path} { if {$base_path eq ""} { error "vivado_to_linty: base path is empty" } if {![file isdirectory $base_path]} { error "vivado_to_linty: not a directory: $base_path" } set base_path [file normalize $base_path] set fs [current_fileset -srcset] set out_ys [file join $base_path "read.ys"] set out_skip [file join $base_path "skipped.txt"] set files [get_files -compile_order sources -used_in synthesis] set ys [open $out_ys w] set skip [open $out_skip w] set n_read 0 foreach f $files { set path [rel_to $base_path [get_property NAME $f]] set typ [string tolower [get_property FILE_TYPE $f]] set lib [get_property LIBRARY $f] if {$lib eq ""} { set lib "xil_defaultlib" } switch -glob -- $typ { "verilog" - "verilog header" - "verilog template" - "systemverilog" - "systemverilog header" { puts $ys "read -sv $path" incr n_read } "vhdl 2008" - "vhdl 2019" - "vhdl" - "vhdl header" { puts $ys "read -vhdl $path" incr n_read } default { puts $skip "$lib\t$typ\t$path" } } } close $ys close $skip puts "read.ys script: $out_ys ($n_read files)" puts "Skipped files: $out_skip" } if {[info exists argv] && [llength $argv] >= 1} { vivado_to_linty [lindex $argv 0] } ``` 1. Save this script as `vivado_to_linty.tcl` 2. From the Tcl console in Vivado, run: ```tcl source /path_to_vivado_to_linty_script/vivado_to_linty.tcl vivado_to_linty /path_to_the_root_of_your_hdl_project ``` ### Elaborate and synthesize your design Add a `hierarchy.ys` file to `.linty/yosys` to set the top module/entity and optionally pass generics/parameters. ```bash # Example #1: Let's say that the top module/entity of your IP is 'dream' # Make sure to pass the name of your top module and not the name of the file containing your top module. hierarchy -top dream ``` ```bash # Example #2: Let's say that the top module/entity of your IP is 'dream' # and that you want to set values for generics/parameters 'ABC' and 'DEF' hierarchy -top dream -chparam ABC 10 -chparam DEF true ``` See [Yosys documentation](https://yosyshq.readthedocs.io/projects/yosys/en/latest/cmd/hierarchy.html) for more details. ### Configuration examples * Simple VHDL project: [https://github.com/Linty-Services/linty-hdl-designer-sample](https://github.com/Linty-Services/linty-hdl-designer-sample/.linty/yosys) * Simple Verilog project reading files from filelist: [https://github.com/Linty-Services/cv32e40p/blob/linty/read.ys](https://github.com/Linty-Services/cv32e40p/blob/linty/.linty/yosys/read.ys) * NEORV32, generating Linty configuration files in GitHub workflow: [https://github.com/stnolting/neorv32/blob/linty_test/.github/workflows/Linty.yml](https://github.com/stnolting/neorv32/blob/linty_test/.github/workflows/Linty.yml) * xifu-irap/fpasim-fw, list of files generated from Vivado with a Tcl command, and configuration of Xilinx third-party libraries (XPM, UNISIM, etc.): [https://github.com/xifu-irap/fpasim-fw/blob/develop/.linty/yosys/read.ys](https://github.com/xifu-irap/fpasim-fw/blob/develop/read.ys) * xifu-irap/dmx-fw, using third-party IP from NanoXplore: [https://github.com/xifu-irap/dmx-fw/blob/develop/.linty/yosys/read.ys](https://github.com/xifu-irap/dmx-fw/blob/develop/read.ys) ## Debug Debug information is available in the `.linty/work/bugfinder/` directory from the root of your repository: * `build.tcl` is the script to synthesize your code and gather information for BugFinder rules * The `logs` directory contains an `output.log` file that is the output of the synthesis execution and gathering of information for BugFinder rules * `*.json` files are data gathered from the synthesized output to feed the Linty [`bug-finder`](https://demo.linty-services.com/coding_rules?tags=bug-finder) rules ## Troubleshooting ### Top module/entity not found If you face the following issue: ``` Executing HIERARCHY pass (managing design hierarchy). Statically elaborating the Verific parse tree. Elaborating all modules in library 'work' [HIER-1013] could not find top-level module/unit; aborting hierarchy tree creation ERROR: Module `xxx' not found! ``` it means that the file containing your top module has not been read. The reason could be that: * There is a typo in the name of the module set as top in [`hierarchy.ys`](#elaborate-and-synthesize-your-design) * The top module has been compiled but in a library that is different from `work`. In the Linty context, make sure to always compile the top module in library `work`. Note that it should be the last instruction of your `read.ys` file. For instance, if your top module is defined in file `top.v`: ```bash ... verific -sv ./top.v # No more instruction ```