add icon of vvp | pass vivado lsp | pass modelsim lsp
This commit is contained in:
parent
010a4b6bec
commit
6773a3df94
17
CHANGELOG.md
17
CHANGELOG.md
@ -7,15 +7,20 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
|
|||||||
## [0.3.2] - 2023-11-01
|
## [0.3.2] - 2023-11-01
|
||||||
|
|
||||||
Bug 修复
|
Bug 修复
|
||||||
- 修复文档化input, output处注释无法正常显示到文档的 bug
|
- 修复文档化 input, output 处注释无法正常显示到文档的 bug
|
||||||
- 修复 iverilog 仿真功能中,将重复的路径作为编译参数编译的 bug
|
- 修复 iverilog 仿真功能中,将重复的路径作为编译参数编译的 bug
|
||||||
- 修复 iverilog 仿真功能中,将 `include 加入或去除后,无法通过仿真编译的 bug (没有更新 instance 的 instModPathStatus 属性)
|
- 修复 iverilog 仿真功能中,将 <code>`include</code> 加入或去除后,无法通过仿真编译的 bug (没有更新 instance 的 instModPathStatus 属性)
|
||||||
|
- 修复其他已知 bug
|
||||||
|
|
||||||
Feat
|
Change
|
||||||
|
- 将插件的工作状态显示在 vscode 下侧的状态栏上,利于用户了解目前的设置状态
|
||||||
|
- 优化项目配置目录
|
||||||
|
|
||||||
|
Feature
|
||||||
- 增加对 XDC,TCL 等脚本的 LSP 支持
|
- 增加对 XDC,TCL 等脚本的 LSP 支持
|
||||||
- 增加 verilog, vhdl, xdc, tcl 等语言的图标
|
- 增加 verilog, vhdl, xdc, tcl, vvp 等语言的工作区图标
|
||||||
- 增加对于 vivado 的支持,用户可以通过添加 vivado 路径的方式(或者将 bin 文件夹添加到环境变量,默认路径为 C:\Xilinx\Vivado\2018.3\bin)来使用 vivado 的仿真和自动纠错
|
- 增加对于 vivado, modelsim, verilator 的支持,用户可以通过设置 `function.lsp.linter.vhdl.diagnostor`(设置 vhdl) 和 `function.lsp.linter.vlog.diagnostor`(设置 verilog) 来使用这些第三方工具的仿真和自动纠错。
|
||||||
- 增加对于 modelsim 的支持,用户可以通过添加 modelsim 安装路径(或者将 bin 文件夹添加到环境变量,默认路径为 C:\modeltech64_10.4\win64)来使用 vivado 的仿真和自动纠错
|
- 增加对于 TCL, XDC, VVP 等脚本的 LSP 和 语法高亮 支持
|
||||||
|
|
||||||
## [0.1.23] - 2022-12-24
|
## [0.1.23] - 2022-12-24
|
||||||
- Finish the css of documentation, see `./css/documentation.css` for detail.
|
- Finish the css of documentation, see `./css/documentation.css` for detail.
|
||||||
|
17
config/vvp.configuration.json
Normal file
17
config/vvp.configuration.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"comments": {
|
||||||
|
"lineComment": "#"
|
||||||
|
},
|
||||||
|
"brackets": [
|
||||||
|
["{", "}"],
|
||||||
|
["[", "]"],
|
||||||
|
["(", ")"]
|
||||||
|
],
|
||||||
|
"autoClosingPairs": [
|
||||||
|
{ "open": "(", "close": ")" },
|
||||||
|
{ "open": "[", "close": "]" },
|
||||||
|
{ "open": "'", "close": "'", "notIn": ["string"] },
|
||||||
|
{ "open": "\"", "close": "\"", "notIn": ["string"] },
|
||||||
|
{ "open": "/*", "close": " */", "notIn": ["string"] }
|
||||||
|
]
|
||||||
|
}
|
1
images/svg/dark/vlang.svg
Normal file
1
images/svg/dark/vlang.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg width="16" height="16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10.86 4.057H5.14c-.612 0-1.113.5-1.113 1.112v5.721c0 .612.5 1.112 1.113 1.112h5.72c.612 0 1.113-.5 1.113-1.112V5.17c0-.612-.5-1.113-1.113-1.113Zm-.934 5.931H6.17V6.231h3.756v3.757ZM6.274 14h-.7v-1.682h.7V14Zm1.403 0h-.7v-1.682h.7V14Zm1.404 0h-.7v-1.682h.7V14Zm1.403 0h-.7v-1.682h.7V14ZM3.712 6.273H2v-.7h1.712v.7Zm0 1.403H2v-.7h1.712v.7Zm0 1.404H2v-.7h1.712v.7Zm0 1.403H2v-.7h1.712v.7ZM14 6.273h-1.712v-.7H14v.7Zm0 1.403h-1.712v-.7H14v.7Zm0 1.404h-1.712v-.7H14v.7Zm0 1.403h-1.712v-.7H14v.7Zm-7.726-6.8h-.7V2h.7v1.682Zm1.403 0h-.7V2h.7v1.682Zm1.404 0h-.7V2h.7v1.682Zm1.403 0h-.7V2h.7v1.682Zm-4.932 7.296a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" fill="#FFCB6B"/></svg>
|
After Width: | Height: | Size: 754 B |
1
images/svg/dark/vvp.svg
Normal file
1
images/svg/dark/vvp.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1701000026046" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10173" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M810.666667 128a85.333333 85.333333 0 0 1 85.333333 85.333333v597.333334a85.333333 85.333333 0 0 1-85.333333 85.333333H213.333333a85.333333 85.333333 0 0 1-85.333333-85.333333V213.333333a85.333333 85.333333 0 0 1 85.333333-85.333333h597.333334zM384 330.965333L202.965333 512 384 693.034667l60.330667-60.373334L323.669333 512l120.661334-120.661333L384 330.965333z m256 0l-60.330667 60.373334L700.330667 512l-120.661334 120.661333L640 693.034667 821.034667 512 640 330.965333z" fill="#98C379" p-id="10174"></path></svg>
|
After Width: | Height: | Size: 851 B |
1
images/svg/light/vvp.svg
Normal file
1
images/svg/light/vvp.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1701000026046" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10173" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M810.666667 128a85.333333 85.333333 0 0 1 85.333333 85.333333v597.333334a85.333333 85.333333 0 0 1-85.333333 85.333333H213.333333a85.333333 85.333333 0 0 1-85.333333-85.333333V213.333333a85.333333 85.333333 0 0 1 85.333333-85.333333h597.333334zM384 330.965333L202.965333 512 384 693.034667l60.330667-60.373334L323.669333 512l120.661334-120.661333L384 330.965333z m256 0l-60.330667 60.373334L700.330667 512l-120.661334 120.661333L640 693.034667 821.034667 512 640 330.965333z" fill="#98C379" p-id="10174"></path></svg>
|
After Width: | Height: | Size: 851 B |
27
package.json
27
package.json
@ -33,11 +33,6 @@
|
|||||||
"Snippets"
|
"Snippets"
|
||||||
],
|
],
|
||||||
"activationEvents": [
|
"activationEvents": [
|
||||||
"onLanguage:verilog",
|
|
||||||
"onLanguage:vhdl",
|
|
||||||
"onLanguage:systemverilog",
|
|
||||||
"onCommand:digital-ide.property-json.generate",
|
|
||||||
"onCommand:digital-ide.property-json.overwrite",
|
|
||||||
"workspaceContains:.vscode/property.json"
|
"workspaceContains:.vscode/property.json"
|
||||||
],
|
],
|
||||||
"contributes": {
|
"contributes": {
|
||||||
@ -831,6 +826,21 @@
|
|||||||
],
|
],
|
||||||
"configuration": "./config/link.configuration.json"
|
"configuration": "./config/link.configuration.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "vvp",
|
||||||
|
"aliases": [
|
||||||
|
"VivadoVerificationPlan"
|
||||||
|
],
|
||||||
|
"extensions": [
|
||||||
|
".vvp",
|
||||||
|
".VVP"
|
||||||
|
],
|
||||||
|
"configuration": "./config/vvp.configuration.json",
|
||||||
|
"icon": {
|
||||||
|
"dark": "./images/svg/dark/vvp.svg",
|
||||||
|
"light": "./images/svg/light/vvp.svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "digital-ide-output",
|
"id": "digital-ide-output",
|
||||||
"mimetypes": [
|
"mimetypes": [
|
||||||
@ -863,7 +873,7 @@
|
|||||||
{
|
{
|
||||||
"language": "vhdl",
|
"language": "vhdl",
|
||||||
"scopeName": "source.vhdl",
|
"scopeName": "source.vhdl",
|
||||||
"path": "./syntaxes/vhdl.json"
|
"path": "./syntaxes/vhdl.tmLanguage.json"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"language": "verilog",
|
"language": "verilog",
|
||||||
@ -875,6 +885,11 @@
|
|||||||
"scopeName": "source.systemverilog",
|
"scopeName": "source.systemverilog",
|
||||||
"path": "./syntaxes/systemverilog.json"
|
"path": "./syntaxes/systemverilog.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"language": "vvp",
|
||||||
|
"scopeName": "source.vvp",
|
||||||
|
"path": "./syntaxes/vvp.tmLanguage.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"language": "digital-ide-output",
|
"language": "digital-ide-output",
|
||||||
"scopeName": "digital-ide.output",
|
"scopeName": "digital-ide.output",
|
||||||
|
@ -78,16 +78,23 @@ function registerLsp(context: vscode.ExtensionContext) {
|
|||||||
vscode.languages.registerCompletionItemProvider(vlogSelector, lspCompletion.vlogMacroCompletionProvider, '`');
|
vscode.languages.registerCompletionItemProvider(vlogSelector, lspCompletion.vlogMacroCompletionProvider, '`');
|
||||||
vscode.languages.registerCompletionItemProvider(vlogSelector, lspCompletion.vlogPositionPortProvider, '.');
|
vscode.languages.registerCompletionItemProvider(vlogSelector, lspCompletion.vlogPositionPortProvider, '.');
|
||||||
vscode.languages.registerCompletionItemProvider(vlogSelector, lspCompletion.vlogCompletionProvider);
|
vscode.languages.registerCompletionItemProvider(vlogSelector, lspCompletion.vlogCompletionProvider);
|
||||||
vscode.languages.registerDocumentSemanticTokensProvider(vlogSelector, lspDocSemantic.vlogDocSenmanticProvider, lspDocSemantic.vlogLegend);
|
// vscode.languages.registerDocumentSemanticTokensProvider(vlogSelector, lspDocSemantic.vlogDocSenmanticProvider, lspDocSemantic.vlogLegend);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// vhdl lsp
|
||||||
|
|
||||||
|
vscode.languages.registerCompletionItemProvider(vhdlSelector, lspCompletion.vhdlCompletionProvider);
|
||||||
|
|
||||||
|
|
||||||
// tcl lsp
|
// tcl lsp
|
||||||
vscode.languages.registerCompletionItemProvider(tclSelector, lspCompletion.tclCompletionProvider);
|
vscode.languages.registerCompletionItemProvider(tclSelector, lspCompletion.tclCompletionProvider);
|
||||||
|
|
||||||
lspLinter.vlogLinter.initialise();
|
// lsp linter
|
||||||
|
// make first symbols in workspace
|
||||||
lspCore.hdlSymbolStorage.initialise();
|
lspCore.hdlSymbolStorage.initialise();
|
||||||
|
lspLinter.vlogLinterManager.initialise();
|
||||||
// vhdl lsp
|
lspLinter.vhdlLinterManager.initialise();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { vlogCompletionProvider, vlogIncludeCompletionProvider, vlogMacroCompletionProvider, vlogPositionPortProvider } from './vlog';
|
import { vlogCompletionProvider, vlogIncludeCompletionProvider, vlogMacroCompletionProvider, vlogPositionPortProvider } from './vlog';
|
||||||
|
import { vhdlCompletionProvider } from './vhdl';
|
||||||
import { tclCompletionProvider } from './tcl';
|
import { tclCompletionProvider } from './tcl';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -6,5 +7,6 @@ export {
|
|||||||
vlogIncludeCompletionProvider,
|
vlogIncludeCompletionProvider,
|
||||||
vlogMacroCompletionProvider,
|
vlogMacroCompletionProvider,
|
||||||
vlogPositionPortProvider,
|
vlogPositionPortProvider,
|
||||||
|
vhdlCompletionProvider,
|
||||||
tclCompletionProvider
|
tclCompletionProvider
|
||||||
};
|
};
|
212
src/function/lsp/completion/vhdl.ts
Normal file
212
src/function/lsp/completion/vhdl.ts
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
import * as vscode from 'vscode';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
|
import * as util from '../util';
|
||||||
|
import { hdlParam } from '../../../hdlParser';
|
||||||
|
import { AbsPath, MainOutput, RelPath, ReportType } from '../../../global';
|
||||||
|
import { Define, Include, RawSymbol } from '../../../hdlParser/common';
|
||||||
|
import { HdlInstance, HdlModule } from '../../../hdlParser/core';
|
||||||
|
import { vhdlKeyword } from '../util/keyword';
|
||||||
|
import { hdlPath } from '../../../hdlFs';
|
||||||
|
import { hdlSymbolStorage } from '../core';
|
||||||
|
|
||||||
|
class VhdlCompletionProvider implements vscode.CompletionItemProvider {
|
||||||
|
public async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): Promise<vscode.CompletionItem[] | vscode.CompletionList<vscode.CompletionItem> | null | undefined> {
|
||||||
|
// console.log('VhdlCompletionProvider');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filePath = hdlPath.toSlash(document.fileName);
|
||||||
|
|
||||||
|
// 1. provide keyword
|
||||||
|
const completions = this.makeKeywordItems(document, position);
|
||||||
|
completions.push(...this.makeCompilerKeywordItems(document, position));
|
||||||
|
completions.push(...this.makeSystemKeywordItems(document, position));
|
||||||
|
|
||||||
|
const symbolResult = await hdlSymbolStorage.getSymbol(filePath);
|
||||||
|
if (!symbolResult) {
|
||||||
|
return completions;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('vhdl symbol result');
|
||||||
|
|
||||||
|
|
||||||
|
// locate at one module
|
||||||
|
const scopeSymbols = util.filterSymbolScope(position, symbolResult.content);
|
||||||
|
if (!scopeSymbols ||
|
||||||
|
!scopeSymbols.module ||
|
||||||
|
!hdlParam.hasHdlModule(filePath, scopeSymbols.module.name)) {
|
||||||
|
// MainOutput.report('Fail to get HdlModule ' + filePath + ' ' + scopeSymbols?.module.name, ReportType.Debug);
|
||||||
|
return completions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find wrapper module
|
||||||
|
const currentModule = hdlParam.getHdlModule(filePath, scopeSymbols.module.name);
|
||||||
|
if (!currentModule) {
|
||||||
|
return completions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. provide modules
|
||||||
|
const suggestModulesPromise = this.provideModules(document, position, filePath, symbolResult.macro.includes);
|
||||||
|
|
||||||
|
// 4. provide params and ports of wrapper module
|
||||||
|
const suggestParamsPortsPromise = this.provideParamsPorts(currentModule);
|
||||||
|
|
||||||
|
// 5. provide nets
|
||||||
|
const suggestNetsPromise = this.provideNets(scopeSymbols.symbols);
|
||||||
|
|
||||||
|
// collect
|
||||||
|
completions.push(...await suggestModulesPromise);
|
||||||
|
completions.push(...await suggestParamsPortsPromise);
|
||||||
|
completions.push(...await suggestNetsPromise);
|
||||||
|
|
||||||
|
return completions;
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private makeKeywordItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
|
||||||
|
const vhdlKeywordItem = [];
|
||||||
|
for (const keyword of vhdlKeyword.keys()) {
|
||||||
|
const clItem = this.makekeywordCompletionItem(keyword);
|
||||||
|
vhdlKeywordItem.push(clItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vhdlKeywordItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private makeCompilerKeywordItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
|
||||||
|
const items = [];
|
||||||
|
const targetRange = document.getWordRangeAtPosition(position, /[`_0-9a-zA-Z]+/);
|
||||||
|
const targetWord = document.getText(targetRange);
|
||||||
|
const prefix = targetWord.startsWith('`') ? '' : '`';
|
||||||
|
for (const keyword of vhdlKeyword.compilerKeys()) {
|
||||||
|
const clItem = new vscode.CompletionItem(keyword, vscode.CompletionItemKind.Keyword);
|
||||||
|
clItem.insertText = new vscode.SnippetString(prefix + keyword);
|
||||||
|
clItem.detail = 'compiler directive';
|
||||||
|
items.push(clItem);
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private makeSystemKeywordItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
|
||||||
|
const items = [];
|
||||||
|
for (const keyword of vhdlKeyword.systemKeys()) {
|
||||||
|
const clItem = new vscode.CompletionItem(keyword, vscode.CompletionItemKind.Method);
|
||||||
|
clItem.insertText = new vscode.SnippetString('\\$' + keyword + '($1);');
|
||||||
|
clItem.detail = 'system task';
|
||||||
|
items.push(clItem);
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private makekeywordCompletionItem(keyword: string): vscode.CompletionItem {
|
||||||
|
const clItem = new vscode.CompletionItem(keyword, vscode.CompletionItemKind.Keyword);
|
||||||
|
clItem.detail = 'keyword';
|
||||||
|
|
||||||
|
switch (keyword) {
|
||||||
|
case 'begin': clItem.insertText = new vscode.SnippetString("begin$1\nend"); break;
|
||||||
|
case 'function': clItem.insertText = new vscode.SnippetString("function ${1:name}\n\nendfunction"); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return clItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async provideModules(document: vscode.TextDocument, position: vscode.Position, filePath: AbsPath, includes: Include[]): Promise<vscode.CompletionItem[]> {
|
||||||
|
const suggestModules: vscode.CompletionItem[] = [];
|
||||||
|
|
||||||
|
const lspVhdlConfig = vscode.workspace.getConfiguration('function.lsp.completion.vhdl');
|
||||||
|
const autoAddInclude: boolean = lspVhdlConfig.get('autoAddInclude', true);
|
||||||
|
const completeWholeInstante: boolean = lspVhdlConfig.get('completeWholeInstante', true);
|
||||||
|
|
||||||
|
const includePaths = new Set<AbsPath>();
|
||||||
|
let lastIncludeLine = 0;
|
||||||
|
for (const include of includes) {
|
||||||
|
const absIncludePath = hdlPath.rel2abs(filePath, include.path);
|
||||||
|
includePaths.add(absIncludePath);
|
||||||
|
lastIncludeLine = Math.max(include.range.end.line, lastIncludeLine);
|
||||||
|
}
|
||||||
|
const insertPosition = new vscode.Position(lastIncludeLine, 0);
|
||||||
|
const insertRange = new vscode.Range(insertPosition, insertPosition);
|
||||||
|
const fileFolder = hdlPath.resolve(filePath, '..');
|
||||||
|
|
||||||
|
// used only when completeWholeInstante is true
|
||||||
|
let completePrefix = '';
|
||||||
|
if (completeWholeInstante) {
|
||||||
|
const wordRange = document.getWordRangeAtPosition(position);
|
||||||
|
const countStart = wordRange ? wordRange.start.character : position.character;
|
||||||
|
const spaceNumber = Math.floor(countStart / 4) * 4;
|
||||||
|
console.log(wordRange, countStart, spaceNumber);
|
||||||
|
|
||||||
|
completePrefix = ' '.repeat(spaceNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// for (const module of hdlParam.getAllHdlModules()) {
|
||||||
|
// const clItem = new vscode.CompletionItem(module.name, vscode.CompletionItemKind.Class);
|
||||||
|
|
||||||
|
// // feature 1 : auto add include path if there's no corresponding include path
|
||||||
|
// if (autoAddInclude && !includePaths.has(module.path)) {
|
||||||
|
// const relPath: RelPath = hdlPath.relative(fileFolder, module.path);
|
||||||
|
// const includeString = '`include "' + relPath + '"\n';
|
||||||
|
// const textEdit = new vscode.TextEdit(insertRange, includeString);
|
||||||
|
// clItem.additionalTextEdits = [textEdit];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // feature 2 : auto complete instance
|
||||||
|
// if (completeWholeInstante) {
|
||||||
|
// const snippetString = instanceVhdlCode(module, '', true);
|
||||||
|
// clItem.insertText = new vscode.SnippetString(snippetString);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// clItem.detail = 'module';
|
||||||
|
// suggestModules.push(clItem);
|
||||||
|
// }
|
||||||
|
|
||||||
|
return suggestModules;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async provideParamsPorts(module: HdlModule): Promise<vscode.CompletionItem[]> {
|
||||||
|
if (!module) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const suggestParamsPorts = [];
|
||||||
|
for (const param of module.params) {
|
||||||
|
const clItem = new vscode.CompletionItem(param.name, vscode.CompletionItemKind.Constant);
|
||||||
|
clItem.detail = 'param';
|
||||||
|
suggestParamsPorts.push(clItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const port of module.ports) {
|
||||||
|
const clItem = new vscode.CompletionItem(port.name, vscode.CompletionItemKind.Interface);
|
||||||
|
clItem.detail = 'port';
|
||||||
|
suggestParamsPorts.push(clItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return suggestParamsPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async provideNets(symbols: RawSymbol[]): Promise<vscode.CompletionItem[]> {
|
||||||
|
if (!symbols) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const suggestNets = [];
|
||||||
|
for (const symbol of symbols) {
|
||||||
|
if (symbol.type === 'wire' || symbol.type === 'reg') {
|
||||||
|
const clItem = new vscode.CompletionItem(symbol.name, vscode.CompletionItemKind.Variable);
|
||||||
|
clItem.sortText = '';
|
||||||
|
clItem.detail = symbol.type;
|
||||||
|
suggestNets.push(clItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return suggestNets;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const vhdlCompletionProvider = new VhdlCompletionProvider();
|
||||||
|
|
||||||
|
export {
|
||||||
|
vhdlCompletionProvider
|
||||||
|
};
|
@ -1,12 +1,16 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
|
import { HdlLangID } from '../../../global/enum';
|
||||||
|
|
||||||
interface BaseLinter {
|
interface BaseLinter {
|
||||||
diagnostic: vscode.DiagnosticCollection;
|
diagnostic: vscode.DiagnosticCollection;
|
||||||
lint(document: vscode.TextDocument): Promise<void>;
|
lint(document: vscode.TextDocument): Promise<void>;
|
||||||
|
remove(uri: vscode.Uri): Promise<void>;
|
||||||
|
initialise(langID: HdlLangID): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BaseManager {
|
interface BaseManager {
|
||||||
initialise(): Promise<void>;
|
initialise(): Promise<void>;
|
||||||
|
updateLinter(): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,13 +73,8 @@ class DefaultVlogLinter implements BaseLinter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async initialise() {
|
public async initialise() {
|
||||||
for (const doc of vscode.workspace.textDocuments) {
|
// move code to outer layer
|
||||||
if (isVerilogFile(doc.fileName)) {
|
return true;
|
||||||
// TODO : check performance
|
|
||||||
await this.lint(doc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LspOutput.report('finish initialization of default vlog linter', ReportType.Launch);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,13 +144,8 @@ class DefaultVHDLLinter implements BaseLinter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async initialise() {
|
public async initialise() {
|
||||||
for (const doc of vscode.workspace.textDocuments) {
|
// move code to outer layer
|
||||||
if (isVhdlFile(doc.fileName)) {
|
return true;
|
||||||
// TODO : check performance
|
|
||||||
await this.lint(doc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LspOutput.report('finish initialization of default vlog linter', ReportType.Launch);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,10 +51,14 @@ class ModelsimLinter implements BaseLinter {
|
|||||||
this.diagnostic.set(document.uri, diagnostics);
|
this.diagnostic.set(document.uri, diagnostics);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LspOutput.report('linter is not available, please check prj.modelsim.install.path in your setting', ReportType.Error);
|
LspOutput.report('modelsim linter is not available, please check prj.modelsim.install.path in your setting!', ReportType.Error, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async remove(uri: vscode.Uri) {
|
||||||
|
this.diagnostic.delete(uri);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param document
|
* @param document
|
||||||
* @param stdout stdout from xvlog
|
* @param stdout stdout from xvlog
|
||||||
@ -62,21 +66,24 @@ class ModelsimLinter implements BaseLinter {
|
|||||||
*/
|
*/
|
||||||
private provideDiagnostics(document: vscode.TextDocument, stdout: string): vscode.Diagnostic[] {
|
private provideDiagnostics(document: vscode.TextDocument, stdout: string): vscode.Diagnostic[] {
|
||||||
const diagnostics = [];
|
const diagnostics = [];
|
||||||
for (const line of stdout.split('\n')) {
|
for (const line of stdout.split(/\r?\n/g)) {
|
||||||
const tokens = line.split(/(Error|Warning).+?(?: *?(?:.+?(?:\\|\/))+.+?\((\d+?)\):|)(?: *?near "(.+?)":|)(?: *?\((.+?)\)|) +?(.+)/gm);
|
const tokens = line.split(/(Error|Warning).+?(?: *?(?:.+?(?:\\|\/))+.+?\((\d+?)\):|)(?: *?near "(.+?)":|)(?: *?\((.+?)\)|) +?(.+)/gm);
|
||||||
|
|
||||||
|
const headerInfo = tokens[1];
|
||||||
const headerInfo = tokens[0];
|
|
||||||
if (headerInfo === 'Error') {
|
if (headerInfo === 'Error') {
|
||||||
const errorLine = parseInt(tokens[2]) - 1;
|
const errorLine = parseInt(tokens[2]) - 1;
|
||||||
const syntaxInfo = tokens[5];
|
const syntaxInfo = tokens[5];
|
||||||
const range = this.makeCorrectRange(document, errorLine);
|
LspOutput.report(`<vlog linter> line: ${errorLine}, info: ${syntaxInfo}`, ReportType.Run);
|
||||||
|
|
||||||
|
const range = this.makeCorrectRange(document, errorLine, syntaxInfo);
|
||||||
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Error);
|
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Error);
|
||||||
diagnostics.push(diag);
|
diagnostics.push(diag);
|
||||||
} else if (headerInfo == 'Warning') {
|
} else if (headerInfo === 'Warning') {
|
||||||
const errorLine = parseInt(tokens[2]) - 1;
|
const errorLine = parseInt(tokens[2]) - 1;
|
||||||
const syntaxInfo = tokens[5];
|
const syntaxInfo = tokens[5];
|
||||||
const range = this.makeCorrectRange(document, errorLine);
|
LspOutput.report(`<vlog linter> line: ${errorLine}, info: ${syntaxInfo}`, ReportType.Run);
|
||||||
|
|
||||||
|
const range = this.makeCorrectRange(document, errorLine, syntaxInfo);
|
||||||
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Warning);
|
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Warning);
|
||||||
diagnostics.push(diag);
|
diagnostics.push(diag);
|
||||||
}
|
}
|
||||||
@ -84,8 +91,32 @@ class ModelsimLinter implements BaseLinter {
|
|||||||
return diagnostics;
|
return diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
private makeCorrectRange(document: vscode.TextDocument, line: number): vscode.Range {
|
private makeCorrectRange(document: vscode.TextDocument, line: number, syntaxInfo: string): vscode.Range {
|
||||||
|
// extract all the words like 'adawwd' in a syntax info
|
||||||
|
const singleQuoteWords = syntaxInfo.match(/'([^']*)'/g);
|
||||||
|
if (singleQuoteWords && singleQuoteWords.length > 0) {
|
||||||
|
const targetWord = singleQuoteWords.map(val => val.replace(/'/g, ''))[0];
|
||||||
|
// find range of target word
|
||||||
|
const textLine = document.lineAt(line);
|
||||||
|
const text = textLine.text;
|
||||||
|
const startCharacter = text.indexOf(targetWord);
|
||||||
|
if (startCharacter > -1) {
|
||||||
|
const endCharacter = startCharacter + targetWord.length;
|
||||||
|
const range = new vscode.Range(
|
||||||
|
new vscode.Position(line, startCharacter),
|
||||||
|
new vscode.Position(line, endCharacter)
|
||||||
|
);
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// else target the first word in the line
|
||||||
|
return this.makeCommonRange(document, line, syntaxInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private makeCommonRange(document: vscode.TextDocument, line: number, syntaxInfo: string): vscode.Range {
|
||||||
const startPosition = new vscode.Position(line, 0);
|
const startPosition = new vscode.Position(line, 0);
|
||||||
|
|
||||||
const wordRange = document.getWordRangeAtPosition(startPosition, /[`_0-9a-zA-Z]+/);
|
const wordRange = document.getWordRangeAtPosition(startPosition, /[`_0-9a-zA-Z]+/);
|
||||||
if (wordRange) {
|
if (wordRange) {
|
||||||
return wordRange;
|
return wordRange;
|
||||||
@ -107,11 +138,11 @@ class ModelsimLinter implements BaseLinter {
|
|||||||
const fullExecutorName = opeParam.os === 'win32' ? executorName + '.exe' : executorName;
|
const fullExecutorName = opeParam.os === 'win32' ? executorName + '.exe' : executorName;
|
||||||
|
|
||||||
if (modelsimInstallPath.trim() === '' || !fs.existsSync(modelsimInstallPath)) {
|
if (modelsimInstallPath.trim() === '' || !fs.existsSync(modelsimInstallPath)) {
|
||||||
LspOutput.report(`User's modelsim Install Path ${modelsimInstallPath}, which is invalid. Use ${executorName} in default.`, ReportType.Warn);
|
LspOutput.report(`User's modelsim Install Path "${modelsimInstallPath}", which is invalid. Use ${executorName} in default.`, ReportType.Warn);
|
||||||
LspOutput.report('If you have doubts, check prj.modelsim.install.path in setting', ReportType.Warn);
|
LspOutput.report('If you have doubts, check prj.modelsim.install.path in setting', ReportType.Warn);
|
||||||
return executorName;
|
return executorName;
|
||||||
} else {
|
} else {
|
||||||
LspOutput.report(`User's modelsim Install Path ${modelsimInstallPath}, which is invalid`);
|
LspOutput.report(`User's modelsim Install Path "${modelsimInstallPath}", which is invalid`);
|
||||||
|
|
||||||
const executorPath = hdlPath.join(
|
const executorPath = hdlPath.join(
|
||||||
hdlPath.toSlash(modelsimInstallPath),
|
hdlPath.toSlash(modelsimInstallPath),
|
||||||
@ -131,23 +162,23 @@ class ModelsimLinter implements BaseLinter {
|
|||||||
}
|
}
|
||||||
const { stderr } = await easyExec(executorPath, []);
|
const { stderr } = await easyExec(executorPath, []);
|
||||||
if (stderr.length === 0) {
|
if (stderr.length === 0) {
|
||||||
this.executableInvokeNameMap.set(langID, undefined);
|
|
||||||
LspOutput.report(`fail to execute ${executorPath}! Reason: ${stderr}`, ReportType.Error);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
this.executableInvokeNameMap.set(langID, executorPath);
|
this.executableInvokeNameMap.set(langID, executorPath);
|
||||||
LspOutput.report(`success to verify ${executorPath}, linter from modelsim is ready to go!`, ReportType.Launch);
|
LspOutput.report(`success to verify ${executorPath}, linter from modelsim is ready to go!`, ReportType.Launch);
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
this.executableInvokeNameMap.set(langID, undefined);
|
||||||
|
LspOutput.report(`fail to execute ${executorPath}! Reason: ${stderr}`, ReportType.Error, true);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public initialise(langID: HdlLangID) {
|
public async initialise(langID: HdlLangID): Promise<boolean> {
|
||||||
const executorPath = this.getExecutableFilePath(langID);
|
const executorPath = this.getExecutableFilePath(langID);
|
||||||
this.setExecutableFilePath(executorPath, langID);
|
return this.setExecutableFilePath(executorPath, langID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const modelsimLinter = new ModelsimLinter()
|
const modelsimLinter = new ModelsimLinter();
|
||||||
|
|
||||||
export {
|
export {
|
||||||
modelsimLinter,
|
modelsimLinter,
|
||||||
|
@ -43,47 +43,59 @@ class VerilatorLinter implements BaseLinter {
|
|||||||
const args = [filePath, ...linterArgs];
|
const args = [filePath, ...linterArgs];
|
||||||
const executor = this.executableInvokeNameMap.get(langID);
|
const executor = this.executableInvokeNameMap.get(langID);
|
||||||
if (executor !== undefined) {
|
if (executor !== undefined) {
|
||||||
const { stdout } = await easyExec(executor, args);
|
const { stderr } = await easyExec(executor, args);
|
||||||
if (stdout.length > 0) {
|
if (stderr.length > 0) {
|
||||||
const diagnostics = this.provideDiagnostics(document, stdout);
|
const diagnostics = this.provideDiagnostics(document, stderr);
|
||||||
this.diagnostic.set(document.uri, diagnostics);
|
this.diagnostic.set(document.uri, diagnostics);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LspOutput.report('linter is not available, please check prj.verilator.install.path in your setting', ReportType.Error);
|
LspOutput.report('verilator linter is not available, please check prj.verilator.install.path in your setting', ReportType.Error, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async remove(uri: vscode.Uri) {
|
||||||
|
this.diagnostic.delete(uri);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param document
|
* @param document
|
||||||
* @param stdout stdout from xvlog
|
* @param stdout stdout from xvlog
|
||||||
* @returns { vscode.Diagnostic[] } linter info
|
* @returns { vscode.Diagnostic[] } linter info
|
||||||
*/
|
*/
|
||||||
private provideDiagnostics(document: vscode.TextDocument, stdout: string): vscode.Diagnostic[] {
|
private provideDiagnostics(document: vscode.TextDocument, stderr: string): vscode.Diagnostic[] {
|
||||||
const diagnostics = [];
|
const diagnostics = [];
|
||||||
for (const line of stdout.split('\n')) {
|
for (let line of stderr.split(/\r?\n/g)) {
|
||||||
const tokens = line.split(/(Error|Warning).+?(?: *?(?:.+?(?:\\|\/))+.+?\((\d+?)\):|)(?: *?near "(.+?)":|)(?: *?\((.+?)\)|) +?(.+)/gm);
|
if (!line.startsWith('%')) {
|
||||||
// TODO : make parser of output info from verilator
|
continue;
|
||||||
|
} else {
|
||||||
|
line = line.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
const headerInfo = tokens[0];
|
const tokens = line.split(':');
|
||||||
if (headerInfo === 'Error') {
|
if (tokens.length < 3) {
|
||||||
const errorLine = parseInt(tokens[2]) - 1;
|
continue;
|
||||||
const syntaxInfo = tokens[5];
|
}
|
||||||
const range = this.makeCorrectRange(document, errorLine);
|
const header = tokens[0].toLowerCase();
|
||||||
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Error);
|
const fileName = tokens[1];
|
||||||
diagnostics.push(diag);
|
const lineNo = parseInt(tokens[2]) - 1;
|
||||||
} else if (headerInfo == 'Warning') {
|
const characterNo = parseInt(tokens[3]) - 1;
|
||||||
const errorLine = parseInt(tokens[2]) - 1;
|
const syntaxInfo = tokens[4];
|
||||||
const syntaxInfo = tokens[5];
|
|
||||||
const range = this.makeCorrectRange(document, errorLine);
|
if (header.startsWith('warning')) {
|
||||||
|
const range = this.makeCorrectRange(document, lineNo, characterNo);
|
||||||
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Warning);
|
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Warning);
|
||||||
diagnostics.push(diag);
|
diagnostics.push(diag);
|
||||||
|
} else if (header.startsWith('error')) {
|
||||||
|
const range = this.makeCorrectRange(document, lineNo, characterNo);
|
||||||
|
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Error);
|
||||||
|
diagnostics.push(diag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return diagnostics;
|
return diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
private makeCorrectRange(document: vscode.TextDocument, line: number): vscode.Range {
|
private makeCorrectRange(document: vscode.TextDocument, line: number, character: number): vscode.Range {
|
||||||
const startPosition = new vscode.Position(line, 0);
|
const startPosition = new vscode.Position(line, character);
|
||||||
const wordRange = document.getWordRangeAtPosition(startPosition, /[`_0-9a-zA-Z]+/);
|
const wordRange = document.getWordRangeAtPosition(startPosition, /[`_0-9a-zA-Z]+/);
|
||||||
if (wordRange) {
|
if (wordRange) {
|
||||||
return wordRange;
|
return wordRange;
|
||||||
@ -129,19 +141,20 @@ class VerilatorLinter implements BaseLinter {
|
|||||||
}
|
}
|
||||||
const { stderr } = await easyExec(executorPath, []);
|
const { stderr } = await easyExec(executorPath, []);
|
||||||
if (stderr.length === 0) {
|
if (stderr.length === 0) {
|
||||||
this.executableInvokeNameMap.set(langID, undefined);
|
|
||||||
LspOutput.report(`fail to execute ${executorPath}! Reason: ${stderr}`, ReportType.Error);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
this.executableInvokeNameMap.set(langID, executorPath);
|
this.executableInvokeNameMap.set(langID, executorPath);
|
||||||
LspOutput.report(`success to verify ${executorPath}, linter from verilator is ready to go!`, ReportType.Launch);
|
LspOutput.report(`success to verify ${executorPath}, linter from verilator is ready to go!`, ReportType.Launch);
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
this.executableInvokeNameMap.set(langID, undefined);
|
||||||
|
LspOutput.report(`fail to execute ${executorPath}! Reason: ${stderr}`, ReportType.Error, true);
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public initialise(langID: HdlLangID) {
|
public async initialise(langID: HdlLangID): Promise<boolean> {
|
||||||
const executorPath = this.getExecutableFilePath(langID);
|
const executorPath = this.getExecutableFilePath(langID);
|
||||||
this.setExecutableFilePath(executorPath, langID);
|
return this.setExecutableFilePath(executorPath, langID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import { BaseLinter, BaseManager } from './base';
|
|||||||
import { defaultVlogLinter } from './default';
|
import { defaultVlogLinter } from './default';
|
||||||
import { modelsimLinter } from './modelsim';
|
import { modelsimLinter } from './modelsim';
|
||||||
import { vivadoLinter } from './vivado';
|
import { vivadoLinter } from './vivado';
|
||||||
|
import { hdlFile, hdlPath } from '../../../hdlFs';
|
||||||
|
|
||||||
class VhdlLinterManager implements BaseManager {
|
class VhdlLinterManager implements BaseManager {
|
||||||
currentLinter: BaseLinter | undefined;
|
currentLinter: BaseLinter | undefined;
|
||||||
@ -17,21 +18,37 @@ class VhdlLinterManager implements BaseManager {
|
|||||||
this.activateList.set('default', false);
|
this.activateList.set('default', false);
|
||||||
this.activateLinterName = 'default';
|
this.activateLinterName = 'default';
|
||||||
|
|
||||||
this.updateLinter();
|
|
||||||
|
|
||||||
// update when user's config is changed
|
// update when user's config is changed
|
||||||
vscode.workspace.onDidChangeConfiguration(() => {
|
vscode.workspace.onDidChangeConfiguration(() => {
|
||||||
const diagnostor = this.getUserDiagnostorSelection();
|
const diagnostor = this.getUserDiagnostorSelection();
|
||||||
const lastDiagnostor = this.activateLinterName;
|
const lastDiagnostor = this.activateLinterName;
|
||||||
if (diagnostor !== lastDiagnostor) {
|
if (diagnostor !== lastDiagnostor) {
|
||||||
LspOutput.report(`[vhdl lsp manager] detect linter setting changes, switch ${lastDiagnostor} to ${diagnostor}.`, );
|
LspOutput.report(`<vhdl lsp manager> detect linter setting changes, switch ${lastDiagnostor} to ${diagnostor}.`, );
|
||||||
this.updateLinter();
|
this.updateLinter();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialise(): Promise<void> {
|
async initialise(): Promise<void> {
|
||||||
|
const success = await this.updateLinter();
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const doc of vscode.workspace.textDocuments) {
|
||||||
|
const fileName = hdlPath.toSlash(doc.fileName);
|
||||||
|
if (hdlFile.isVhdlFile(fileName)) {
|
||||||
|
await this.lint(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LspOutput.report('<vhdl lsp manager> finish initialization of vhdl linter. Linter name: ' + this.activateLinterName, ReportType.Launch);
|
||||||
|
}
|
||||||
|
|
||||||
|
async lint(document: vscode.TextDocument) {
|
||||||
|
await this.currentLinter?.lint(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(uri: vscode.Uri): Promise<void> {
|
||||||
|
this.currentLinter?.remove(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getUserDiagnostorSelection() {
|
public getUserDiagnostorSelection() {
|
||||||
@ -40,53 +57,59 @@ class VhdlLinterManager implements BaseManager {
|
|||||||
return diagnostor;
|
return diagnostor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateLinter() {
|
public async updateLinter(): Promise<boolean> {
|
||||||
const diagnostor = this.getUserDiagnostorSelection();
|
const diagnostor = this.getUserDiagnostorSelection();
|
||||||
switch (diagnostor) {
|
switch (diagnostor) {
|
||||||
case 'vivado': this.activateVivado(); break;
|
case 'vivado': return this.activateVivado();
|
||||||
case 'modelsim': this.activateModelsim(); break;
|
case 'modelsim': return this.activateModelsim();
|
||||||
case 'default': this.activateDefault(); break;
|
case 'default': return this.activateDefault();
|
||||||
case default: this.activateDefault(); break;
|
default: return this.activateDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public activateVivado() {
|
public async activateVivado(): Promise<boolean> {
|
||||||
const selectedLinter = vivadoLinter;
|
const selectedLinter = vivadoLinter;
|
||||||
|
let launch = true;
|
||||||
|
|
||||||
if (this.activateList.get('vivado') === false) {
|
if (this.activateList.get('vivado') === false) {
|
||||||
selectedLinter.initialise(HdlLangID.Verilog);
|
launch = await selectedLinter.initialise(HdlLangID.Verilog);
|
||||||
this.activateList.set('vivado', true);
|
this.activateList.set('vivado', true);
|
||||||
LspOutput.report('[vhdl lsp manager] vivado linter has been activated', ReportType.Info);
|
LspOutput.report('<vhdl lsp manager> vivado linter has been activated', ReportType.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentLinter = selectedLinter;
|
this.currentLinter = selectedLinter;
|
||||||
this.activateLinterName = 'vivado';
|
this.activateLinterName = 'vivado';
|
||||||
|
return launch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public activateModelsim() {
|
public async activateModelsim(): Promise<boolean> {
|
||||||
const selectedLinter = modelsimLinter;
|
const selectedLinter = modelsimLinter;
|
||||||
|
let launch = true;
|
||||||
|
|
||||||
if (this.activateList.get('modelsim') === false) {
|
if (this.activateList.get('modelsim') === false) {
|
||||||
selectedLinter.initialise(HdlLangID.Verilog);
|
launch = await selectedLinter.initialise(HdlLangID.Verilog);
|
||||||
this.activateList.set('modelsim', true);
|
this.activateList.set('modelsim', true);
|
||||||
LspOutput.report('[vhdl lsp manager] modelsim linter has been activated', ReportType.Info);
|
LspOutput.report('<vhdl lsp manager> modelsim linter has been activated', ReportType.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentLinter = selectedLinter;
|
this.currentLinter = selectedLinter;
|
||||||
this.activateLinterName = 'modelsim';
|
this.activateLinterName = 'modelsim';
|
||||||
|
return launch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public activateDefault() {
|
public async activateDefault(): Promise<boolean> {
|
||||||
const selectedLinter = defaultVlogLinter;
|
const selectedLinter = defaultVlogLinter;
|
||||||
|
let launch = true;
|
||||||
|
|
||||||
if (this.activateList.get('default') === false) {
|
if (this.activateList.get('default') === false) {
|
||||||
|
|
||||||
this.activateList.set('default', true);
|
this.activateList.set('default', true);
|
||||||
LspOutput.report('[vhdl lsp manager] default build-in linter has been activated', ReportType.Info);
|
LspOutput.report('<vhdl lsp manager> default build-in linter has been activated', ReportType.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentLinter = selectedLinter;
|
this.currentLinter = selectedLinter;
|
||||||
this.activateLinterName = 'default';
|
this.activateLinterName = 'default';
|
||||||
|
return launch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +54,14 @@ class VivadoLinter implements BaseLinter {
|
|||||||
this.diagnostic.set(document.uri, diagnostics);
|
this.diagnostic.set(document.uri, diagnostics);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LspOutput.report('linter is not available, please check prj.vivado.install.path in your setting', ReportType.Error);
|
LspOutput.report('vivado linter is not available, please check prj.vivado.install.path in your setting', ReportType.Error, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async remove(uri: vscode.Uri) {
|
||||||
|
this.diagnostic.delete(uri);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param document
|
* @param document
|
||||||
* @param stdout stdout from xvlog
|
* @param stdout stdout from xvlog
|
||||||
@ -65,7 +69,7 @@ class VivadoLinter implements BaseLinter {
|
|||||||
*/
|
*/
|
||||||
private provideDiagnostics(document: vscode.TextDocument, stdout: string): vscode.Diagnostic[] {
|
private provideDiagnostics(document: vscode.TextDocument, stdout: string): vscode.Diagnostic[] {
|
||||||
const diagnostics = [];
|
const diagnostics = [];
|
||||||
for (const line of stdout.split('\n')) {
|
for (const line of stdout.split(/\r?\n/g)) {
|
||||||
const tokens = line.split(/:?\s*(?:\[|\])\s*/);
|
const tokens = line.split(/:?\s*(?:\[|\])\s*/);
|
||||||
const headerInfo = tokens[0];
|
const headerInfo = tokens[0];
|
||||||
// const standardInfo = tokens[1];
|
// const standardInfo = tokens[1];
|
||||||
@ -73,8 +77,10 @@ class VivadoLinter implements BaseLinter {
|
|||||||
const parsedPath = tokens[3];
|
const parsedPath = tokens[3];
|
||||||
if (headerInfo === 'ERROR') {
|
if (headerInfo === 'ERROR') {
|
||||||
const errorInfos = parsedPath.split(':');
|
const errorInfos = parsedPath.split(':');
|
||||||
const errorLine = parseInt(errorInfos[errorInfos.length - 1]);
|
const errorLine = Math.max(parseInt(errorInfos[errorInfos.length - 1]) - 1, 0);
|
||||||
const range = this.makeCorrectRange(document, errorLine);
|
LspOutput.report(`<xvlog linter> line: ${errorLine}, info: ${syntaxInfo}`, ReportType.Run);
|
||||||
|
|
||||||
|
const range = this.makeCorrectRange(document, errorLine, syntaxInfo);
|
||||||
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Error);
|
const diag = new vscode.Diagnostic(range, syntaxInfo, vscode.DiagnosticSeverity.Error);
|
||||||
diagnostics.push(diag);
|
diagnostics.push(diag);
|
||||||
}
|
}
|
||||||
@ -82,8 +88,32 @@ class VivadoLinter implements BaseLinter {
|
|||||||
return diagnostics;
|
return diagnostics;
|
||||||
}
|
}
|
||||||
|
|
||||||
private makeCorrectRange(document: vscode.TextDocument, line: number): vscode.Range {
|
private makeCorrectRange(document: vscode.TextDocument, line: number, syntaxInfo: string): vscode.Range {
|
||||||
|
// extract all the words like 'adawwd' in a syntax info
|
||||||
|
const singleQuoteWords = syntaxInfo.match(/'([^']*)'/g);
|
||||||
|
if (singleQuoteWords && singleQuoteWords.length > 0) {
|
||||||
|
const targetWord = singleQuoteWords.map(val => val.replace(/'/g, ''))[0];
|
||||||
|
// find range of target word
|
||||||
|
const textLine = document.lineAt(line);
|
||||||
|
const text = textLine.text;
|
||||||
|
const startCharacter = text.indexOf(targetWord);
|
||||||
|
if (startCharacter > -1) {
|
||||||
|
const endCharacter = startCharacter + targetWord.length;
|
||||||
|
const range = new vscode.Range(
|
||||||
|
new vscode.Position(line, startCharacter),
|
||||||
|
new vscode.Position(line, endCharacter)
|
||||||
|
);
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// else target the first word in the line
|
||||||
|
return this.makeCommonRange(document, line, syntaxInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private makeCommonRange(document: vscode.TextDocument, line: number, syntaxInfo: string): vscode.Range {
|
||||||
const startPosition = new vscode.Position(line, 0);
|
const startPosition = new vscode.Position(line, 0);
|
||||||
|
|
||||||
const wordRange = document.getWordRangeAtPosition(startPosition, /[`_0-9a-zA-Z]+/);
|
const wordRange = document.getWordRangeAtPosition(startPosition, /[`_0-9a-zA-Z]+/);
|
||||||
if (wordRange) {
|
if (wordRange) {
|
||||||
return wordRange;
|
return wordRange;
|
||||||
@ -105,11 +135,11 @@ class VivadoLinter implements BaseLinter {
|
|||||||
const fullExecutorName = opeParam.os === 'win32' ? executorName + '.bat' : executorName;
|
const fullExecutorName = opeParam.os === 'win32' ? executorName + '.bat' : executorName;
|
||||||
|
|
||||||
if (vivadoInstallPath.trim() === '' || !fs.existsSync(vivadoInstallPath)) {
|
if (vivadoInstallPath.trim() === '' || !fs.existsSync(vivadoInstallPath)) {
|
||||||
LspOutput.report(`User's Vivado Install Path ${vivadoInstallPath}, which is invalid. Use ${executorName} in default.`, ReportType.Warn);
|
LspOutput.report(`User's Vivado Install Path "${vivadoInstallPath}", which is invalid. Use ${executorName} in default.`, ReportType.Warn);
|
||||||
LspOutput.report('If you have doubts, check prj.vivado.install.path in setting', ReportType.Warn);
|
LspOutput.report('If you have doubts, check prj.vivado.install.path in setting', ReportType.Warn);
|
||||||
return executorName;
|
return executorName;
|
||||||
} else {
|
} else {
|
||||||
LspOutput.report(`User's Vivado Install Path ${vivadoInstallPath}, which is invalid`);
|
LspOutput.report(`User's Vivado Install Path "${vivadoInstallPath}", which is invalid`);
|
||||||
|
|
||||||
const executorPath = hdlPath.join(
|
const executorPath = hdlPath.join(
|
||||||
hdlPath.toSlash(vivadoInstallPath),
|
hdlPath.toSlash(vivadoInstallPath),
|
||||||
@ -129,19 +159,19 @@ class VivadoLinter implements BaseLinter {
|
|||||||
}
|
}
|
||||||
const { stderr } = await easyExec(executorPath, []);
|
const { stderr } = await easyExec(executorPath, []);
|
||||||
if (stderr.length === 0) {
|
if (stderr.length === 0) {
|
||||||
this.executableInvokeNameMap.set(langID, undefined);
|
|
||||||
LspOutput.report(`fail to execute ${executorPath}! Reason: ${stderr}`, ReportType.Error);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
this.executableInvokeNameMap.set(langID, executorPath);
|
this.executableInvokeNameMap.set(langID, executorPath);
|
||||||
LspOutput.report(`success to verify ${executorPath}, linter from vivado is ready to go!`, ReportType.Launch);
|
LspOutput.report(`success to verify ${executorPath}, linter from vivado is ready to go!`, ReportType.Launch);
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
this.executableInvokeNameMap.set(langID, undefined);
|
||||||
|
LspOutput.report(`fail to execute ${executorPath}! Reason: ${stderr}`, ReportType.Error, true);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public initialise(langID: HdlLangID) {
|
public async initialise(langID: HdlLangID): Promise<boolean> {
|
||||||
const executorPath = this.getExecutableFilePath(langID);
|
const executorPath = this.getExecutableFilePath(langID);
|
||||||
this.setExecutableFilePath(executorPath, langID);
|
return this.setExecutableFilePath(executorPath, langID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import { BaseLinter, BaseManager } from './base';
|
|||||||
import { defaultVlogLinter } from './default';
|
import { defaultVlogLinter } from './default';
|
||||||
import { modelsimLinter } from './modelsim';
|
import { modelsimLinter } from './modelsim';
|
||||||
import { vivadoLinter } from './vivado';
|
import { vivadoLinter } from './vivado';
|
||||||
|
import { hdlFile, hdlPath } from '../../../hdlFs';
|
||||||
|
|
||||||
class VlogLinterManager implements BaseManager {
|
class VlogLinterManager implements BaseManager {
|
||||||
currentLinter: BaseLinter | undefined;
|
currentLinter: BaseLinter | undefined;
|
||||||
@ -17,21 +18,39 @@ class VlogLinterManager implements BaseManager {
|
|||||||
this.activateList.set('default', false);
|
this.activateList.set('default', false);
|
||||||
this.activateLinterName = 'default';
|
this.activateLinterName = 'default';
|
||||||
|
|
||||||
this.updateLinter();
|
|
||||||
|
|
||||||
// update when user's config is changed
|
// update when user's config is changed
|
||||||
vscode.workspace.onDidChangeConfiguration(() => {
|
vscode.workspace.onDidChangeConfiguration(() => {
|
||||||
const diagnostor = this.getUserDiagnostorSelection();
|
const diagnostor = this.getUserDiagnostorSelection();
|
||||||
const lastDiagnostor = this.activateLinterName;
|
const lastDiagnostor = this.activateLinterName;
|
||||||
if (diagnostor !== lastDiagnostor) {
|
if (diagnostor !== lastDiagnostor) {
|
||||||
LspOutput.report(`detect linter setting changes, switch ${lastDiagnostor} to ${diagnostor}.`, );
|
LspOutput.report(`<vlog lsp manager> detect linter setting changes, switch ${lastDiagnostor} to ${diagnostor}.`, );
|
||||||
this.updateLinter();
|
this.updateLinter();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialise(): Promise<void> {
|
async initialise(): Promise<void> {
|
||||||
|
const success = await this.updateLinter();
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const doc of vscode.workspace.textDocuments) {
|
||||||
|
const fileName = hdlPath.toSlash(doc.fileName);
|
||||||
|
if (hdlFile.isVerilogFile(fileName)) {
|
||||||
|
await this.lint(doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LspOutput.report('<vlog lsp manager> finish initialization of vlog linter. Linter name: ' + this.activateLinterName, ReportType.Launch);
|
||||||
|
}
|
||||||
|
|
||||||
|
async lint(document: vscode.TextDocument) {
|
||||||
|
await this.currentLinter?.lint(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(uri: vscode.Uri): Promise<void> {
|
||||||
|
this.currentLinter?.remove(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getUserDiagnostorSelection() {
|
public getUserDiagnostorSelection() {
|
||||||
@ -40,53 +59,59 @@ class VlogLinterManager implements BaseManager {
|
|||||||
return diagnostor;
|
return diagnostor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateLinter() {
|
public async updateLinter() {
|
||||||
const diagnostor = this.getUserDiagnostorSelection();
|
const diagnostor = this.getUserDiagnostorSelection();
|
||||||
switch (diagnostor) {
|
switch (diagnostor) {
|
||||||
case 'vivado': this.activateVivado(); break;
|
case 'vivado': return this.activateVivado();
|
||||||
case 'modelsim': this.activateModelsim(); break;
|
case 'modelsim': return this.activateModelsim();
|
||||||
case 'default': this.activateDefault(); break;
|
case 'default': return this.activateDefault();
|
||||||
case default: this.activateDefault(); break;
|
default: return this.activateDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public activateVivado() {
|
public async activateVivado(): Promise<boolean> {
|
||||||
const selectedLinter = vivadoLinter;
|
const selectedLinter = vivadoLinter;
|
||||||
|
let launch = true;
|
||||||
|
|
||||||
if (this.activateList.get('vivado') === false) {
|
if (this.activateList.get('vivado') === false) {
|
||||||
selectedLinter.initialise(HdlLangID.Verilog);
|
launch = await selectedLinter.initialise(HdlLangID.Verilog);
|
||||||
this.activateList.set('vivado', true);
|
this.activateList.set('vivado', true);
|
||||||
LspOutput.report('vivado linter has been activated', ReportType.Info);
|
LspOutput.report('<vlog lsp manager> vivado linter has been activated', ReportType.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentLinter = selectedLinter;
|
this.currentLinter = selectedLinter;
|
||||||
this.activateLinterName = 'vivado';
|
this.activateLinterName = 'vivado';
|
||||||
|
return launch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public activateModelsim() {
|
public async activateModelsim(): Promise<boolean> {
|
||||||
const selectedLinter = modelsimLinter;
|
const selectedLinter = modelsimLinter;
|
||||||
|
let launch = true;
|
||||||
|
|
||||||
if (this.activateList.get('modelsim') === false) {
|
if (this.activateList.get('modelsim') === false) {
|
||||||
selectedLinter.initialise(HdlLangID.Verilog);
|
launch = await selectedLinter.initialise(HdlLangID.Verilog);
|
||||||
this.activateList.set('modelsim', true);
|
this.activateList.set('modelsim', true);
|
||||||
LspOutput.report('modelsim linter has been activated', ReportType.Info);
|
LspOutput.report('<vlog lsp manager> modelsim linter has been activated', ReportType.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentLinter = selectedLinter;
|
this.currentLinter = selectedLinter;
|
||||||
this.activateLinterName = 'modelsim';
|
this.activateLinterName = 'modelsim';
|
||||||
|
return launch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public activateDefault() {
|
public async activateDefault(): Promise<boolean> {
|
||||||
const selectedLinter = defaultVlogLinter;
|
const selectedLinter = defaultVlogLinter;
|
||||||
|
let launch = true;
|
||||||
|
|
||||||
if (this.activateList.get('default') === false) {
|
if (this.activateList.get('default') === false) {
|
||||||
|
|
||||||
this.activateList.set('default', true);
|
this.activateList.set('default', true);
|
||||||
LspOutput.report('default build-in linter has been activated', ReportType.Info);
|
LspOutput.report('<vlog lsp manager> default build-in linter has been activated', ReportType.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentLinter = selectedLinter;
|
this.currentLinter = selectedLinter;
|
||||||
this.activateLinterName = 'default';
|
this.activateLinterName = 'default';
|
||||||
|
return launch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@ import { hdlParam, HdlSymbol } from '../hdlParser';
|
|||||||
import { prjManage } from '../manager';
|
import { prjManage } from '../manager';
|
||||||
import { libManage } from '../manager/lib';
|
import { libManage } from '../manager/lib';
|
||||||
import type { HdlMonitor } from './index';
|
import type { HdlMonitor } from './index';
|
||||||
import { ToolChainType } from '../global/enum';
|
import { HdlLangID, ToolChainType } from '../global/enum';
|
||||||
import { hdlSymbolStorage } from '../function/lsp/core';
|
import { hdlSymbolStorage } from '../function/lsp/core';
|
||||||
import { vlogLinter } from '../function/lsp/linter';
|
import { vlogLinterManager, vhdlLinterManager } from '../function/lsp/linter';
|
||||||
import { isVerilogFile } from '../hdlFs/file';
|
import { isVerilogFile } from '../hdlFs/file';
|
||||||
|
|
||||||
enum Event {
|
enum Event {
|
||||||
@ -98,7 +98,12 @@ class HdlAction extends BaseAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uri = vscode.Uri.file(path);
|
const uri = vscode.Uri.file(path);
|
||||||
vlogLinter.remove(uri);
|
const langID = hdlFile.getLanguageId(path);
|
||||||
|
if (langID === HdlLangID.Verilog) {
|
||||||
|
vlogLinterManager.remove(uri);
|
||||||
|
} else if (langID === HdlLangID.Vhdl) {
|
||||||
|
vhdlLinterManager.remove(uri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async unlinkDir(path: string, m: HdlMonitor): Promise<void> {
|
async unlinkDir(path: string, m: HdlMonitor): Promise<void> {
|
||||||
@ -128,10 +133,16 @@ class HdlAction extends BaseAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateLinter(path: string) {
|
async updateLinter(path: string) {
|
||||||
if (isVerilogFile(path)) {
|
const uri = vscode.Uri.file(path);
|
||||||
const uri = vscode.Uri.file(path);
|
const document = await vscode.workspace.openTextDocument(uri);
|
||||||
const document = await vscode.workspace.openTextDocument(uri);
|
const langID = hdlFile.getLanguageId(path);
|
||||||
vlogLinter.lint(document);
|
|
||||||
|
if (langID === HdlLangID.Verilog) {
|
||||||
|
vlogLinterManager.lint(document);
|
||||||
|
} else if (langID === HdlLangID.Vhdl) {
|
||||||
|
vhdlLinterManager.lint(document);
|
||||||
|
} else if (langID === HdlLangID.SystemVerilog) {
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "digital-ide.Launch",
|
||||||
|
"match": "(\\[Launch - (.*)\\])([\\s\\S]*)",
|
||||||
|
"captures": {
|
||||||
|
"1": {
|
||||||
|
"name": "keyword.launch-token"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"name": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "string.quoted.double",
|
"name": "string.quoted.double",
|
||||||
"begin": "\"",
|
"begin": "\"",
|
||||||
|
361
syntaxes/vvp.tmLanguage.json
Normal file
361
syntaxes/vvp.tmLanguage.json
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
{
|
||||||
|
"fileTypes": [
|
||||||
|
"v",
|
||||||
|
"vh"
|
||||||
|
],
|
||||||
|
"keyEquivalent": "^~V",
|
||||||
|
"name": "Verilog",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#comments"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#module_pattern"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#keywords"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#constants"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#strings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#operators"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#macro_definition"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#macro_quote"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#common_variable"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"comments": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"begin": "(^[ \\t]+)?(?=#)",
|
||||||
|
"beginCaptures": {
|
||||||
|
"1": {
|
||||||
|
"name": "punctuation.whitespace.comment.leading.verilog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "(?!\\G)",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"begin": "#",
|
||||||
|
"beginCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.definition.comment.verilog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "\\n",
|
||||||
|
"name": "comment.line.double-slash.verilog"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"begin": "/\\*",
|
||||||
|
"end": "\\*/",
|
||||||
|
"name": "comment.block.c-style.verilog"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"constants": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "\\b[0-9]+'[bBoOdDhH][a-fA-F0-9_xXzZ]+\\b",
|
||||||
|
"name": "constant.numeric.sized_integer.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"captures": {
|
||||||
|
"1": {
|
||||||
|
"name": "constant.numeric.integer.verilog"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"name": "punctuation.separator.range.verilog"
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"name": "constant.numeric.integer.verilog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"match": "\\b(\\d+)(:)(\\d+)\\b",
|
||||||
|
"name": "meta.block.numeric.range.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\b\\d+(?i:e\\d+)?\\b",
|
||||||
|
"name": "constant.numeric.integer.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\b\\d+\\.\\d+(?i:e\\d+)?\\b",
|
||||||
|
"name": "constant.numeric.real.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "#\\d+",
|
||||||
|
"name": "constant.numeric.delay.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\b[01xXzZ]+\\b",
|
||||||
|
"name": "constant.numeric.logic.verilog"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"instantiation_patterns": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#keywords"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"begin": "^\\s*([a-zA-Z][a-zA-Z0-9_]*)\\s+([a-zA-Z][a-zA-Z0-9_]*)(?<!begin|if)\\s*(?=\\(|$)",
|
||||||
|
"beginCaptures": {
|
||||||
|
"1": {
|
||||||
|
"name": "entity.name.class.module.reference.verilog"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"name": "entity.name.function.module.identifier.verilog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": ";",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.terminator.expression.verilog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "variable.other.constant.instantiation.parameterless.verilog",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#comments"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#constants"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#strings"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"begin": "^\\s*([a-zA-Z][a-zA-Z0-9_]*)\\s*(#)(?=\\s*\\()",
|
||||||
|
"beginCaptures": {
|
||||||
|
"1": {
|
||||||
|
"name": "entity.name.class.module.reference.verilog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": ";",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.terminator.expression.verilog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "support.block.instantiation.with.parameters.verilog",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#parenthetical_list"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "[a-zA-Z][a-zA-Z0-9_]*",
|
||||||
|
"name": "entity.name.function.module.identifier.verilog"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"keywords": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "\\b(always|and|assign|attribute|begin|buf|bufif0|bufif1|case(xz)?|cmos|deassign|default|defparam|disable|edge|else|end(attribute|case|function|generate|module|primitive|specify|table|task)?|event|for|force|forever|fork|function|generate|genvar|highz(01)|if(none)?|initial|inout|input|integer|join|localparam|medium|module|large|macromodule|nand|negedge|nmos|nor|not|notif(01)|or|output|parameter|pmos|posedge|primitive|pull0|pull1|pulldown|pullup|rcmos|real|realtime|reg|release|repeat|rnmos|rpmos|rtran|rtranif(01)|scalared|signed|small|specify|specparam|strength|strong0|strong1|supply0|supply1|table|task|time|tran|tranif(01)|tri(01)?|tri(and|or|reg)|unsigned|vectored|wait|wand|weak(01)|while|wire|wor|xnor|xor)\\b",
|
||||||
|
"name": "keyword.other.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "^\\s*`((cell)?define|default_(decay_time|nettype|trireg_strength)|delay_mode_(path|unit|zero)|ifdef|include|end(if|celldefine)|else|(no)?unconnected_drive|resetall|timescale|undef)\\b",
|
||||||
|
"name": "keyword.other.compiler.directive.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\$(f(open|close)|readmem(b|h)|timeformat|printtimescale|stop|finish|(s|real)?time|realtobits|bitstoreal|rtoi|itor|(f)?(display|write(h|b)))\\b",
|
||||||
|
"name": "support.function.system.console.tasks.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\$(random|dist_(chi_square|erlang|exponential|normal|poisson|t|uniform))\\b",
|
||||||
|
"name": "support.function.system.random_number.tasks.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\$((a)?sync\\$((n)?and|(n)or)\\$(array|plane))\\b",
|
||||||
|
"name": "support.function.system.pld_modeling.tasks.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\$(q_(initialize|add|remove|full|exam))\\b",
|
||||||
|
"name": "support.function.system.stochastic.tasks.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\$(hold|nochange|period|recovery|setup(hold)?|skew|width)\\b",
|
||||||
|
"name": "support.function.system.timing.tasks.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\$(dump(file|vars|off|on|all|limit|flush))\\b",
|
||||||
|
"name": "support.function.system.vcd.tasks.verilog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": "\\$(countdrivers|list|input|scope|showscopes|(no)?(key|log)|reset(_count|_value)?|(inc)?save|restart|showvars|getpattern|sreadmem(b|h)|scale)",
|
||||||
|
"name": "support.function.non-standard.tasks.verilog"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"module_pattern": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"begin": "\\b(module)\\s+([a-zA-Z][a-zA-Z0-9_]*)",
|
||||||
|
"beginCaptures": {
|
||||||
|
"1": {
|
||||||
|
"name": "storage.type.module.verilog"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"name": "entity.name.type.module.verilog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "\\bendmodule\\b",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "storage.type.module.verilog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "meta.block.module.verilog",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#comments"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#keywords"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#constants"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#strings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#instantiation_patterns"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#operators"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#position_ports"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#macro_quote"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#common_variable"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"operators": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "\\+|-|\\*|/|%|(<|>)=?|(!|=)?==?|!|&&?|\\|\\|?|\\^?~|~\\^?",
|
||||||
|
"name": "keyword.operator.verilog"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"parenthetical_list": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"begin": "\\(",
|
||||||
|
"beginCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.section.list.verilog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"end": "\\)",
|
||||||
|
"endCaptures": {
|
||||||
|
"0": {
|
||||||
|
"name": "punctuation.section.list.verilog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "support.block.parenthetical_list.verilog",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#parenthetical_list"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#comments"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#keywords"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#constants"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#strings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#position_ports"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#macro_quote"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#common_variable"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"position_ports": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "\\.[a-zA-Z_][a-zA-Z_0-9]*",
|
||||||
|
"name": "variable.inst.port.verilog"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"strings": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"begin": "\"",
|
||||||
|
"end": "\"",
|
||||||
|
"name": "string.quoted.double.verilog",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "\\\\.",
|
||||||
|
"name": "constant.character.escape.verilog"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"macro_definition": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "(?<=`define\\s)\\w+",
|
||||||
|
"name": "support.function.macro.definition.verilog"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"macro_quote": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "`[a-zA-Z_][a-zA-Z_0-9]*",
|
||||||
|
"name": "support.function.macro.quote.verilog"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"common_variable": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"match": "[a-zA-Z_][a-zA-Z_0-9]*",
|
||||||
|
"name": "variable.other.constant.verilog"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scopeName": "source.vvp",
|
||||||
|
"uuid": "7F4396B3-A33E-44F0-8502-98CA6C25971F"
|
||||||
|
}
|
8
test/vlogFast.js
Normal file
8
test/vlogFast.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
const { vlogFast } = require('../resources/hdlParser');
|
||||||
|
|
||||||
|
const testFile = 'c:/Users/11934/Project/Digital-IDE/Digital-Test/Verilog/dependence_test/parent.v';
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const fast = vlogFast(testFile);
|
||||||
|
console.log(JSON.stringify(fast, null, ' '));
|
||||||
|
})();
|
Loading…
x
Reference in New Issue
Block a user