start lsp

This commit is contained in:
锦恢 2023-04-22 22:17:18 +08:00
parent 8a4fc5bb70
commit b16f9bf104
9 changed files with 272 additions and 100 deletions

View File

@ -6,10 +6,7 @@ type RelPath = string;
type Path = AbsPath | RelPath;
interface Fast {
content: {
error : string[]
modules: RawHdlModule[]
}
content: RawHdlModule[]
languageId: HdlLangID
macro: Macro
}

View File

@ -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 = {

View File

View 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;
*/
}
}

View File

@ -188,24 +188,24 @@ class HdlParam {
this.unhandleInstances.delete(inst);
}
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) {
// 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);
}
}
this.doHdlFast(path);
}
}

View File

@ -1,5 +1,7 @@
import { hdlParam } from './core';
import { HdlSymbol } from './util';
export {
hdlParam
hdlParam,
HdlSymbol
};

View File

@ -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;
}

View File

@ -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] != ""} {

View File

@ -18,7 +18,13 @@ 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());
@ -26,8 +32,19 @@ function registerManagerCommands(context: vscode.ExtensionContext) {
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 {