@imc-trading/svlangserver
Version:
A language server for systemverilog
321 lines (293 loc) • 13.1 kB
Markdown
# SVLangserver
A language server for systemverilog that has been tested to work with coc.nvim, VSCode, Sublime Text 4 and emacs
## Features
- Auto completion (no need for ctags or other such mechanisms)
- Go to symbol in document
- Go to symbol in workspace folder (indexed modules/interfaces/packages)
- Go to definition (_works for module/interface/package names and for ports too!_)
- Hover over help
- Signature help
- Fast indexing
- Verilator/Icarus linting on the fly
- Report hierarchy of a module
- Code snippets for many common blocks
- Code formatting with verible-verilog-format
- Elaborate syntax highlighting (for VSCode)
## Versions
The code has been tested to work with below tool versions
- vim 8.2
* coc.nvim 0.0.80-0b5130ea38
- VSCode 1.52.0
- Sublime Text Build 4126
- emacs 29.0.50
* lsp-mode lsp-mode-20220328.1429
- Neovim 0.7.0
- Verilator 4.110
- Icarus Verilog Compiler 10.2
- Verible v0.0-1114-ged89c1b
## Installation
- For coc.nvim
* `npm install -g @imc-trading/svlangserver`
* Update .vim/coc-settings.json
- For VSCode
* Install the extension from the marketplace.
* Update the settings
- For Sublime Text 3
* Install the systemverilog package in sublime text
* `npm install -g @imc-trading/svlangserver`
* Update the LSP settings (`Preferences -> Package Settings -> LSP -> settings`) and the sublime-project files
- For emacs
* Install lsp-mode
* `npm install -g @imc-trading/svlangserver`
* Update .emacs/init.el
- For neovim
* Install [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)
* `npm install -g @imc-trading/svlangserver`
* Add following setting in your init.lua
```lua
require'lspconfig'.svlangserver.setup{}
```
* Update .nvim/lspconfig.json
To get the snippets, git clone this repo and copy the snippets directory wherever applicable
For installing from source (not applicable for VSCode)
- `git clone https://github.com/imc-trading/svlangserver.git`
- `cd svlangserver && npm install`
* Update the settings with the correct command (e.g. `/git/repo/path/svlangserver/bin/main.js`)
NOTE: This has been tested with npm version 6.14.13 and node version 14.17.1
## Settings
- `systemverilog.includeIndexing`: _Array_, Globs defining files to be indexed
- `systemverilog.libraryIndexing`: _Array_, Globs defining library files to be added to linting. It's useful when module name is not equal to filename.
- `systemverilog.excludeIndexing`: _Array_, Exclude files from indexing based on glob
- `systemverilog.linter`: _String_, Select linter
* Default: _'verilator'_
- `systemverilog.launchConfiguration`: _String_, Command to run for launching linting
* Default: _verilator --sv --lint-only --Wall_
* If not in path, replace _verilator_ with the appropriate command
- `systemverilog.lintOnUnsaved`: _Boolean_, Lint even unsaved files
* Default: _true_
- `systemverilog.defines`: _Array_, Defines for the project. Used by the language server as well as linting
* Default: _empty_
- `systemverilog.formatCommand`: _String_, verible-verilog-format command for code formatting
* Default: _verible-verilog-format_
* If not in path, replace _verible-verilog-format_ with the appropriate command
- `systemverilog.disableCompletionProvider`: _Boolean_, Disable auto completion provided by the language server
* Default: _false_
- `systemverilog.disableHoverProvider`: _Boolean_, Disable hover over help provided by the language server
* Default: _false_
- `systemverilog.disableSignatureHelpProvider`: _Boolean_, Disable signature help provided by the language server
* Default: _false_
- `systemverilog.disableLinting`: _Boolean_, Disable linting
* Default: _false_
- Example coc.nvim settings file
```json
{
"languageserver": {
"svlangserver": {
"command": "svlangserver",
"filetypes": ["systemverilog"],
"settings": {
"systemverilog.includeIndexing": ["**/*.{sv,svh}"],
"systemverilog.excludeIndexing": ["test/**/*.sv*"],
"systemverilog.defines" : [],
"systemverilog.launchConfiguration": "/tools/verilator -sv -Wall --lint-only",
"systemverilog.formatCommand": "/tools/verible-verilog-format"
}
}
}
}
```
For project specific settings this file should be at `<WORKSPACE PATH>/.vim/coc-settings.json`
- Example coc.nvim settings file (for windows)
```json
{
"languageserver": {
"svlangserver": {
"module": "/usr/lib/node_modules/@imc-trading/svlangserver/bin/main.js",
"args": ["--node-ipc"],
"filetypes": ["systemverilog"],
"settings": {
"systemverilog.includeIndexing": ["**/*.{sv,svh}"],
"systemverilog.excludeIndexing": ["test/**/*.sv*"],
"systemverilog.defines" : [],
"systemverilog.launchConfiguration": "/tools/verilator -sv -Wall --lint-only",
"systemverilog.formatCommand": "/tools/verible-verilog-format"
}
}
}
}
```
For project specific settings this file should be at `<WORKSPACE PATH>\.vim\coc-settings.json`
- Example vscode settings file
```json
{
"systemverilog.includeIndexing": ["**/*.{sv,svh}"],
"systemverilog.excludeIndexing": ["test/**/*.sv*"],
"systemverilog.defines" : [],
"systemverilog.launchConfiguration": "/tools/verilator -sv -Wall --lint-only",
"systemverilog.formatCommand": "/tools/verible-verilog-format"
}
```
For project specific settings this file should be at `<WORKSPACE PATH>/.vscode/settings.json`
- Example Sublime Text 3 settings files
* The global LSP settings file: LSP.sublime-settings
```json
{
"clients": {
"svlangserver": {
"enabled": true,
"command": ["svlangserver"],
"languageId": "systemverilog",
"scopes": ["source.systemverilog"],
"syntaxes": ["Packages/SystemVerilog/SystemVerilog.sublime-syntax"],
"settings": {
"systemverilog.disableHoverProvider": true,
"systemverilog.launchConfiguration": "/tools/verilator -sv --lint-only -Wall",
"systemverilog.formatCommand" : "/tools/verible-verilog-format"
}
}
}
}
```
* The project specific settings go in `<PROJECT>.sublime-project`
```json
{
"folders":
[
{
"path": "."
}
],
"settings": {
"LSP": {
"svlangserver": {
"settings": {
"systemverilog.includeIndexing": [ "**/*.{sv,svh}", ],
"systemverilog.excludeIndexing": ["test/**/*.sv*"],
"systemverilog.defines": [],
}
}
}
}
}
```
- Example settings for emacs
* Below content goes in .emacs or init.el
```elisp
(require 'lsp-verilog)
(custom-set-variables
'(lsp-clients-svlangserver-launchConfiguration "/tools/verilator -sv --lint-only -Wall")
'(lsp-clients-svlangserver-formatCommand "/tools/verible-verilog-format"))
(add-hook 'verilog-mode-hook #'lsp-deferred)
```
* The project specific settings go in .dir-locals.el
```elisp
((verilog-mode (lsp-clients-svlangserver-workspace-additional-dirs . ("/some/lib/path"))
(lsp-clients-svlangserver-includeIndexing . ("src/**/*.{sv,svh}"))
(lsp-clients-svlangserver-excludeIndexing . ("src/test/**/*.{sv,svh}"))))
```
- Example neovim settings file
```json
{
"languageserver": {
"svlangserver": {
"command": "svlangserver",
"filetypes": ["systemverilog"],
"settings": {
"systemverilog.includeIndexing": ["**/*.{sv,svh}"],
"systemverilog.excludeIndexing": ["test/**/*.sv*"],
"systemverilog.defines" : [],
"systemverilog.launchConfiguration": "/tools/verilator -sv -Wall --lint-only",
"systemverilog.formatCommand": "/tools/verible-verilog-format"
}
}
}
}
```
For project specific settings this file should be at `<WORKSPACE PATH>/.nvim/lspconfig.json`
## Commands
* `systemverilog.build_index`: Instructs language server to rerun indexing
* `systemverilog.report_hierarchy`: Generates hierarchy for the given module
### coc.nvim usage
* The commands should be executed using CocRequest function. An example vim command would be:
```vim
command! SvBuildIndex call CocRequest("svlangserver", 'workspace/executeCommand', {'command': 'systemverilog.build_index'})
command! -range SvReportHierarchy call CocRequest("svlangserver", 'workspace/executeCommand', {'command': 'systemverilog.report_hierarchy', 'arguments': [input('Module/interface: ', <range> == 0 ? "" : expand("<cword>"))]})
```
If the above SvReportHierarchy command is called with visual selection, then the module name is pre-filled with the selection. Also depending on the coc.nvim version, the generated rpt.json file might not have the focus and user will have to switch buffer manually.
### VSCode usage
* Typing `build index` in the command palette should invoke the build index command.
* Typing `get hierarchy` in the command palette should invoke the report hierarchy command. If invoked with an active slection, the module name is pre-filled with the selection.
### Sublime usage
* A sublime-commands file needs to be created with the below content
```json
[
{
"caption": "SvLangserver Build Index",
"command": "lsp_execute",
"args": {
"session_name": "svlangserver",
"command_name": "systemverilog.build_index",
"command_args": []
}
},
{
"caption": "Svlangserver Report Hierarchy",
"command": "lsp_execute",
"args": {
"session_name": "svlangserver",
"command_name": "systemverilog.report_hierarchy",
"command_args": ["${selection}"]
}
}
]
```
This should make the commands available in the command palette. For the report hierarchy command, the module name should be selected before invoking the command.
### Emacs usage
* `lsp-clients-svlangserver-build-index` command should rerun the indexing.
* `lsp-clients-svlangserver-report-hierarchy` command should do the job. If invoked with an active slection, the module name is pre-filled with the selection.
### Neovim usage
* `:SvlangserverBuildIndex` command should rerun the indexing.
* `:SvlangserverReportHierarchy` command will generate hierarchy file of the word under the cursor in normal mode.
## Troubleshooting
- Editor is not able to find language server binary.
* Make sure the binary is in the system path as exposed to the editor. If the binary is installed in custom directory, expose that path to your editor
- Not getting any diagnostics
* Make sure the launchConfiguration setting has been properly set to use verilator from the correct installation path
- Diagnostics show _Cannot find file containing module 'module_name'_
* Make sure all submodules can be found by includeIndexing
* If the issue still remains, it may due to different naming of module and file, or a file containing multiple modules. Make sure these files can be found by libraryIndexing.
- Check settings used by the language server
* for coc.nvim: Use the command `:CocCommand workspace.showOutput` and then select svlangserver
* for vscode: Check the SVLangServer output channel
* for sublime: Open the command palette in the tools menu and select `LSP: Toggle Log Panel`
* for emacs: Check the `*lsp-log*` buffer
* for neovim: Add `vim.lsp.set_log_level("info")` in your init.lua then check ~/.cache/nvim/lsp.log
## Known Issues
- Language server doesn't understand most verification specific concepts (e.g. classes).
## Future
Rewrite parser to make it much more robust
## Acknowledgements
Although most of the code is written from scratch, this [VSCode-SystemVerilog extension](https://github.com/eirikpre/VSCode-SystemVerilog/) was what I started with and developed on.
## Release Notes
See the [changelog](CHANGELOG.md) for more details
### 0.4.1
- Support for Neovim client with nvim-lspconfig
- Updated settings for faster indexing
- Bug fixes
### 0.4.0
- Icarus as linting alternative
- Command for reporting hierarchy
- Improved hover over formatting
- Improved symbol resolution
- Bug fixes
### 0.3.5
- Improvements to auto-completion and jump to definition
- Bug fixes
### 0.3.4
- Bug fixes
### 0.3.3
- Updated instructions to use published packages
### 0.3.1
- Add support for Sublime LSP and Emacs
### 0.3.0
- Initial release