start lsp
This commit is contained in:
parent
8a4fc5bb70
commit
b16f9bf104
5
resources/hdlParser/index.d.ts
vendored
5
resources/hdlParser/index.d.ts
vendored
@ -6,10 +6,7 @@ type RelPath = string;
|
||||
type Path = AbsPath | RelPath;
|
||||
|
||||
interface Fast {
|
||||
content: {
|
||||
error : string[]
|
||||
modules: RawHdlModule[]
|
||||
}
|
||||
content: RawHdlModule[]
|
||||
languageId: HdlLangID
|
||||
macro: Macro
|
||||
}
|
||||
|
@ -18,62 +18,40 @@ const _hdlParser = {
|
||||
}
|
||||
};
|
||||
|
||||
async function vlogFast(path) {
|
||||
if (!fs.existsSync(path)) {
|
||||
return undefined;
|
||||
}
|
||||
const wasmModule = await _hdlParser.acquire();
|
||||
const source = fs.readFileSync(path, 'utf-8') + '\n';
|
||||
wasmModule.FS.writeFile(_hdlParser.tempPath, source, { encoding: 'utf8' });
|
||||
const res = wasmModule.ccall('vlog_fast', 'string', ['string'], [_hdlParser.tempPath]);
|
||||
try {
|
||||
return JSON.parse(res);
|
||||
} catch (err) {
|
||||
console.log(res);
|
||||
fs.writeFileSync('./draft.json', res);
|
||||
console.log('error happen when parse ' + path);
|
||||
console.log(err);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
async function vlogAll(path) {
|
||||
if (!fs.existsSync(path)) {
|
||||
return undefined;
|
||||
}
|
||||
async function callParser(path, func) {
|
||||
const wasmModule = await _hdlParser.acquire();
|
||||
const file = _hdlParser.tempPath;
|
||||
const fileLength = file.length;
|
||||
const source = fs.readFileSync(path, 'utf-8') + '\n';
|
||||
wasmModule.FS.writeFile(_hdlParser.tempPath, source, { encoding: 'utf8' });
|
||||
const res = wasmModule.ccall('vlog_all', 'string', ['string'], [_hdlParser.tempPath]);
|
||||
const res = wasmModule.ccall('call_parser', 'string', ['string', 'int', 'int'], [file, fileLength, func]);
|
||||
return JSON.parse(res);
|
||||
}
|
||||
|
||||
|
||||
async function vhdlFast(path) {
|
||||
if (!fs.existsSync(path)) {
|
||||
return undefined;
|
||||
}
|
||||
return {};
|
||||
return await callParser(path, 1);
|
||||
}
|
||||
|
||||
async function vhdlAll(path) {
|
||||
if (!fs.existsSync(path)) {
|
||||
return undefined;
|
||||
}
|
||||
return {};
|
||||
return await callParser(path, 2);
|
||||
}
|
||||
|
||||
async function svFast(path) {
|
||||
if (!fs.existsSync(path)) {
|
||||
return undefined;
|
||||
}
|
||||
return {};
|
||||
return await callParser(path, 3);
|
||||
}
|
||||
|
||||
async function svAll(path) {
|
||||
if (!fs.existsSync(path)) {
|
||||
return undefined;
|
||||
}
|
||||
return {};
|
||||
return await callParser(path, 4);
|
||||
}
|
||||
|
||||
async function vlogFast(path) {
|
||||
return await callParser(path, 5);
|
||||
}
|
||||
|
||||
async function vlogAll(path) {
|
||||
return await callParser(path, 6);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
0
src/function/lsp/docSymbol/index.ts
Normal file
0
src/function/lsp/docSymbol/index.ts
Normal file
187
src/function/lsp/docSymbol/vlog.ts
Normal file
187
src/function/lsp/docSymbol/vlog.ts
Normal file
@ -0,0 +1,187 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { HdlSymbol } from '../../../hdlParser';
|
||||
|
||||
class VlogDocSymbolProvider implements vscode.DocumentSymbolProvider {
|
||||
|
||||
public provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.ProviderResult<vscode.SymbolInformation[] | vscode.DocumentSymbol[]> {
|
||||
const code = document.getText();
|
||||
const symbolResult = HdlSymbol.all(code);
|
||||
const symbols = symbolResult.symbols;
|
||||
|
||||
if (!symbols) {
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const symbolInfos = this.makeSymbolInfos(document, symbols);
|
||||
return symbolInfos;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {vscode.TextDocument} document
|
||||
* @param {Array<SymbolResult>} symbols
|
||||
* @returns {Array<vscode.DocumentSymbol>}
|
||||
*/
|
||||
makeSymbolInfos(document: vscode.TextDocument, symbols: SymbolResult[]) {
|
||||
let docSymbols = [];
|
||||
const visitedSymbols = new Set();
|
||||
const moduleSymbols = symbols.filter(symbol => {
|
||||
if (symbol.type == 'module') {
|
||||
visitedSymbols.add(symbol);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
for (const moduleSymbol of moduleSymbols) {
|
||||
const moduleName = moduleSymbol.name;
|
||||
const moduleKind = this.getSymbolKind(moduleSymbol.type);
|
||||
const moduleRange = new vscode.Range(moduleSymbol.start, moduleSymbol.end);
|
||||
const moduleDocSymbol = new vscode.DocumentSymbol(moduleName,
|
||||
moduleName,
|
||||
moduleKind,
|
||||
moduleRange,
|
||||
moduleRange);
|
||||
docSymbols.push(moduleDocSymbol);
|
||||
let paramContainer = {
|
||||
docSymbol: null,
|
||||
range: null
|
||||
};
|
||||
let portContainer = {
|
||||
docSymbol: null,
|
||||
range: null
|
||||
};
|
||||
|
||||
// make others in module inner
|
||||
for (const symbol of symbols) {
|
||||
if (visitedSymbols.has(symbol)) {
|
||||
continue;
|
||||
}
|
||||
if (!(positionAfterEqual(symbol.start, moduleSymbol.start) &&
|
||||
positionAfterEqual(moduleSymbol.end, symbol.end))) {
|
||||
continue;
|
||||
}
|
||||
if (!symbol.name) {
|
||||
symbol.name = '???';
|
||||
}
|
||||
visitedSymbols.add(symbol);
|
||||
const symbolRange = new vscode.Range(symbol.start, symbol.end);
|
||||
|
||||
if (symbol.type == 'parameter') {
|
||||
if (!paramContainer.range) {
|
||||
paramContainer.range = symbolRange;
|
||||
paramContainer.docSymbol = new vscode.DocumentSymbol('param',
|
||||
'param description',
|
||||
vscode.SymbolKind.Method,
|
||||
symbolRange,
|
||||
symbolRange);
|
||||
moduleDocSymbol.children.push(paramContainer.docSymbol);
|
||||
}
|
||||
const paramDocSymbol = new vscode.DocumentSymbol(symbol.name,
|
||||
symbol.type,
|
||||
vscode.SymbolKind.Constant,
|
||||
symbolRange,
|
||||
symbolRange);
|
||||
paramContainer.docSymbol.children.push(paramDocSymbol);
|
||||
|
||||
} else if (['input', 'inout', 'output'].includes(symbol.type)) {
|
||||
if (!portContainer.range) {
|
||||
portContainer.range = symbolRange;
|
||||
portContainer.docSymbol = new vscode.DocumentSymbol('port',
|
||||
'port description',
|
||||
vscode.SymbolKind.Method,
|
||||
symbolRange,
|
||||
symbolRange);
|
||||
moduleDocSymbol.children.push(portContainer.docSymbol);
|
||||
}
|
||||
|
||||
const portDocSymbol = new vscode.DocumentSymbol(symbol.name,
|
||||
symbol.type,
|
||||
vscode.SymbolKind.Interface,
|
||||
symbolRange,
|
||||
symbolRange);
|
||||
portContainer.docSymbol.children.push(portDocSymbol);
|
||||
} else {
|
||||
const symbolKind = this.getSymbolKind(symbol.type);
|
||||
const symbolDocSymbol = new vscode.DocumentSymbol(symbol.name,
|
||||
symbol.type,
|
||||
symbolKind,
|
||||
symbolRange,
|
||||
symbolRange);
|
||||
moduleDocSymbol.children.push(symbolDocSymbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return docSymbols;
|
||||
}
|
||||
|
||||
|
||||
getSymbolKind(name) {
|
||||
if (name.indexOf('[') != -1) {
|
||||
return vscode.SymbolKind.Array;
|
||||
}
|
||||
switch (name) {
|
||||
case 'module': return vscode.SymbolKind.Class;
|
||||
case 'program': return vscode.SymbolKind.Module;
|
||||
case 'package': return vscode.SymbolKind.Package;
|
||||
case 'import': return vscode.SymbolKind.Package;
|
||||
case 'always': return vscode.SymbolKind.Operator;
|
||||
case 'processe': return vscode.SymbolKind.Operator;
|
||||
|
||||
case 'task': return vscode.SymbolKind.Method;
|
||||
case 'function': return vscode.SymbolKind.Function;
|
||||
|
||||
case 'assert': return vscode.SymbolKind.Boolean;
|
||||
case 'event': return vscode.SymbolKind.Event;
|
||||
case 'instance': return vscode.SymbolKind.Event;
|
||||
|
||||
case 'time': return vscode.SymbolKind.TypeParameter;
|
||||
case 'define': return vscode.SymbolKind.TypeParameter;
|
||||
case 'typedef': return vscode.SymbolKind.TypeParameter;
|
||||
case 'generate': return vscode.SymbolKind.Operator;
|
||||
case 'enum': return vscode.SymbolKind.Enum;
|
||||
case 'modport': return vscode.SymbolKind.Boolean;
|
||||
case 'property': return vscode.SymbolKind.Property;
|
||||
|
||||
// port
|
||||
case 'interface': return vscode.SymbolKind.Interface;
|
||||
case 'buffer': return vscode.SymbolKind.Interface;
|
||||
case 'output': return vscode.SymbolKind.Interface;
|
||||
case 'input': return vscode.SymbolKind.Interface;
|
||||
case 'inout': return vscode.SymbolKind.Interface;
|
||||
|
||||
// synth param
|
||||
case 'localparam': return vscode.SymbolKind.Constant;
|
||||
case 'parameter': return vscode.SymbolKind.Constant;
|
||||
case 'integer': return vscode.SymbolKind.Number;
|
||||
case 'char': return vscode.SymbolKind.Number;
|
||||
case 'float': return vscode.SymbolKind.Number;
|
||||
case 'int': return vscode.SymbolKind.Number;
|
||||
|
||||
// unsynth param
|
||||
case 'string': return vscode.SymbolKind.String;
|
||||
case 'struct': return vscode.SymbolKind.Struct;
|
||||
case 'class': return vscode.SymbolKind.Class;
|
||||
|
||||
case 'logic': return vscode.SymbolKind.Constant;
|
||||
case 'wire': return vscode.SymbolKind.Constant;
|
||||
case 'reg': return vscode.SymbolKind.Constant;
|
||||
case 'net': return vscode.SymbolKind.Variable;
|
||||
case 'bit': return vscode.SymbolKind.Boolean;
|
||||
default: return vscode.SymbolKind.Event;
|
||||
}
|
||||
/* Unused/Free SymbolKind icons
|
||||
return SymbolKind.Number;
|
||||
return SymbolKind.Enum;
|
||||
return SymbolKind.EnumMember;
|
||||
return SymbolKind.Operator;
|
||||
return SymbolKind.Array;
|
||||
*/
|
||||
}
|
||||
}
|
@ -188,24 +188,24 @@ class HdlParam {
|
||||
this.unhandleInstances.delete(inst);
|
||||
}
|
||||
|
||||
public async initHdlFiles(hdlFiles: AbsPath[] | Generator<AbsPath>) {
|
||||
for (const path of hdlFiles) {
|
||||
// TODO : only support verilog now
|
||||
const langID = hdlFile.getLanguageId(path);
|
||||
if (langID === HdlLangID.Verilog) {
|
||||
try {
|
||||
const fast = await HdlSymbol.fast(path);
|
||||
if (fast) {
|
||||
new HdlFile(path,
|
||||
fast.languageId,
|
||||
fast.macro,
|
||||
fast.content.modules);
|
||||
}
|
||||
} catch (error) {
|
||||
MainOutput.report('Error happen when parse ' + path, ReportType.Error);
|
||||
MainOutput.report('Reason: ' + error, ReportType.Error);
|
||||
}
|
||||
private async doHdlFast(path: AbsPath) {
|
||||
try {
|
||||
const fast = await HdlSymbol.fast(path);
|
||||
if (fast) {
|
||||
new HdlFile(path,
|
||||
fast.languageId,
|
||||
fast.macro,
|
||||
fast.content);
|
||||
}
|
||||
} catch (error) {
|
||||
MainOutput.report('Error happen when parse ' + path, ReportType.Error);
|
||||
MainOutput.report('Reason: ' + error, ReportType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public async initHdlFiles(hdlFiles: AbsPath[] | Generator<AbsPath>) {
|
||||
for (const path of hdlFiles) {
|
||||
this.doHdlFast(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { hdlParam } from './core';
|
||||
import { HdlSymbol } from './util';
|
||||
|
||||
export {
|
||||
hdlParam
|
||||
hdlParam,
|
||||
HdlSymbol
|
||||
};
|
@ -40,43 +40,42 @@ class PlManage extends BaseManage {
|
||||
}
|
||||
|
||||
|
||||
launch() {
|
||||
public launch() {
|
||||
this.config.ope.launch(this.config);
|
||||
}
|
||||
|
||||
refresh() {
|
||||
public simulate() {
|
||||
if (!this.config.terminal) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.config.ope.refresh(this.config.terminal);
|
||||
}
|
||||
|
||||
simulate() {
|
||||
if (!this.config.terminal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.config.ope.simulate(this.config);
|
||||
}
|
||||
|
||||
build() {
|
||||
if (!this.config.terminal) {
|
||||
return null;
|
||||
}
|
||||
public simulateCli() {
|
||||
this.config.ope.simulateCli(this.config);
|
||||
}
|
||||
|
||||
public simulateGui() {
|
||||
this.config.ope.simulateGui(this.config);
|
||||
}
|
||||
|
||||
public refresh() {
|
||||
if (!this.config.terminal) {
|
||||
return;
|
||||
}
|
||||
this.config.ope.refresh(this.config.terminal);
|
||||
}
|
||||
|
||||
public build() {
|
||||
this.config.ope.build(this.config);
|
||||
}
|
||||
|
||||
synth() {
|
||||
if (!this.config.terminal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public synth() {
|
||||
this.config.ope.synth(this.config);
|
||||
}
|
||||
|
||||
impl() {
|
||||
public impl() {
|
||||
if (!this.config.terminal) {
|
||||
return null;
|
||||
}
|
||||
@ -84,27 +83,19 @@ class PlManage extends BaseManage {
|
||||
this.config.ope.impl(this.config);
|
||||
}
|
||||
|
||||
bit() {
|
||||
if (!this.config.terminal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public bitstream() {
|
||||
this.config.ope.generateBit(this.config);
|
||||
}
|
||||
|
||||
program() {
|
||||
if (!this.config.terminal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public program() {
|
||||
this.config.ope.program(this.config);
|
||||
}
|
||||
|
||||
gui() {
|
||||
public gui() {
|
||||
this.config.ope.gui(this.config);
|
||||
}
|
||||
|
||||
exit() {
|
||||
public exit() {
|
||||
if (!this.config.terminal) {
|
||||
return null;
|
||||
}
|
||||
|
@ -289,10 +289,10 @@ class XilinxOperation {
|
||||
}
|
||||
|
||||
simulate(config: PLConfig) {
|
||||
this.simcli(config);
|
||||
this.simulateCli(config);
|
||||
}
|
||||
|
||||
simgui(config: PLConfig) {
|
||||
simulateGui(config: PLConfig) {
|
||||
const scriptPath = `${this.xilinxPath}/simulate.tcl`;
|
||||
const script = `
|
||||
if {[current_sim] != ""} {
|
||||
@ -319,7 +319,7 @@ class XilinxOperation {
|
||||
config.terminal?.sendText(cmd);
|
||||
}
|
||||
|
||||
simcli(config: PLConfig) {
|
||||
simulateCli(config: PLConfig) {
|
||||
const scriptPath = hdlPath.join(this.xilinxPath, 'simulate.tcl');
|
||||
const script = `
|
||||
if {[current_sim] != ""} {
|
||||
|
@ -18,16 +18,33 @@ function registerManagerCommands(context: vscode.ExtensionContext) {
|
||||
// libpick
|
||||
vscode.commands.registerCommand('digital-ide.pickLibrary', pickLibrary);
|
||||
|
||||
// ps
|
||||
// ps toolbox commands (soft tool in treeView)
|
||||
// TODO : finish digital-ide.soft.download
|
||||
vscode.commands.registerCommand('digital-ide.soft.launch', () => psManage.launch());
|
||||
vscode.commands.registerCommand('digital-ide.soft.build', () => psManage.build());
|
||||
vscode.commands.registerCommand('digital-ide.soft.download', () => psManage.program());
|
||||
|
||||
// pl functional commands
|
||||
vscode.commands.registerCommand('digital-ide.pl.setSrcTop', (item) => plManage.setSrcTop(item));
|
||||
vscode.commands.registerCommand('digital-ide.pl.setSimTop', (item) => plManage.setSimTop(item));
|
||||
vscode.commands.registerCommand('digital-ide.pl.addDevice', () => plManage.addDevice());
|
||||
vscode.commands.registerCommand('digital-ide.pl.delDevice', () => plManage.delDevice());
|
||||
vscode.commands.registerCommand('digital-ide.pl.addFile', files => plManage.addFiles(files));
|
||||
vscode.commands.registerCommand('digital-ide.pl.delFile', files => plManage.delFiles(files));
|
||||
|
||||
// pl
|
||||
|
||||
// pl toolbox commands (hard tool in treeView)
|
||||
vscode.commands.registerCommand('digital-ide.hard.launch', () => plManage.launch());
|
||||
vscode.commands.registerCommand('digital-ide.hard.simulate', () => plManage.simulate());
|
||||
vscode.commands.registerCommand('digital-ide.hard.simulate.cli', () => plManage.simulateCli());
|
||||
vscode.commands.registerCommand('digital-ide.hard.simulate.gui', () => plManage.simulateGui());
|
||||
vscode.commands.registerCommand('digital-ide.hard.refresh', () => plManage.refresh());
|
||||
vscode.commands.registerCommand('digital-ide.hard.build', () => plManage.build());
|
||||
vscode.commands.registerCommand('digital-ide.hard.build.synth', () => plManage.synth());
|
||||
vscode.commands.registerCommand('digital-ide.hard.build.impl', () => plManage.impl());
|
||||
vscode.commands.registerCommand('digital-ide.hard.build.bitstream', () => plManage.bitstream());
|
||||
vscode.commands.registerCommand('digital-ide.hard.program', () => plManage.program());
|
||||
vscode.commands.registerCommand('digital-ide.hard.gui', () => plManage.gui());
|
||||
vscode.commands.registerCommand('digital-ide.hard.exit', () => plManage.exit());
|
||||
}
|
||||
|
||||
export {
|
||||
|
Loading…
x
Reference in New Issue
Block a user