This commit is contained in:
锦恢 2024-09-17 22:40:44 +08:00
commit a348b40a33
11 changed files with 239 additions and 61 deletions

View File

@ -593,7 +593,10 @@
{
"command": "digital-ide.tool.icarus.simulateFile",
"group": "inline@1",
"when": "view == digital-ide-treeView-arch && viewItem == file"
"when": "view == digital-ide-treeView-arch && viewItem == file",
"args": {
"file": "${viewItem}"
}
},
{
"command": "digital-ide.netlist.show",

View File

@ -82,6 +82,8 @@ async function patchComment(path: AbsPath, ports: (HdlModulePort | HdlModulePara
}
const ranges = ports.map(port => port.range);
const comments = await getSymbolComments(path, ranges);
console.log(ranges);
for (let i = 0; i < ports.length; ++ i) {
let inlineComment = comments[i].replace(/\n/, ' ');
if (inlineComment.startsWith('//') || inlineComment.startsWith('--')) {

View File

@ -20,6 +20,7 @@ import * as lspCore from './lsp/core';
import * as FSM from './fsm';
import * as Netlist from './netlist';
import * as WaveView from './dide-viewer';
import { ModuleDataItem } from './treeView/tree';
function registerDocumentation(context: vscode.ExtensionContext) {
vscode.commands.registerCommand('digital-ide.hdlDoc.showWebview', hdlDoc.showDocWebview);
@ -30,7 +31,9 @@ function registerDocumentation(context: vscode.ExtensionContext) {
function registerSimulation(context: vscode.ExtensionContext) {
vscode.commands.registerCommand('digital-ide.tool.instance', sim.instantiation);
vscode.commands.registerCommand('digital-ide.tool.testbench', sim.testbench);
vscode.commands.registerCommand('digital-ide.tool.icarus.simulateFile', sim.Icarus.simulateFile);
vscode.commands.registerCommand('digital-ide.tool.icarus.simulateFile', (view: ModuleDataItem) => {
sim.Icarus.simulateFile(view);
});
}
function registerFunctionCommands(context: vscode.ExtensionContext) {
@ -82,10 +85,10 @@ function registerLsp(context: vscode.ExtensionContext) {
// vhdl lsp
// vscode.languages.registerDocumentSymbolProvider(vhdlSelector, lspDocSymbol.vhdlDocSymbolProvider);
// vscode.languages.registerDefinitionProvider(vhdlSelector, lspDefinition.vhdlDefinitionProvider);
// vscode.languages.registerHoverProvider(vhdlSelector, lspHover.vhdlHoverProvider);
// vscode.languages.registerCompletionItemProvider(vhdlSelector, lspCompletion.vhdlCompletionProvider);
vscode.languages.registerDocumentSymbolProvider(vhdlSelector, lspDocSymbol.vhdlDocSymbolProvider);
vscode.languages.registerDefinitionProvider(vhdlSelector, lspDefinition.vhdlDefinitionProvider);
vscode.languages.registerHoverProvider(vhdlSelector, lspHover.vhdlHoverProvider);
vscode.languages.registerCompletionItemProvider(vhdlSelector, lspCompletion.vhdlCompletionProvider);
// tcl lsp

View File

@ -110,12 +110,12 @@ class VlogHoverProvider implements vscode.HoverProvider {
*
*/
if (util.isPositionInput(lineText, position.character)) {
console.log('enter position input');
// console.log('enter position input');
const currentInstResult = util.filterInstanceByPosition(position, scopeSymbols.symbols, currentModule);
if (!currentInstResult || !currentInstResult.instModPath) {
return null;
}
console.log(currentInstResult);
// console.log(currentInstResult);
const instParamPromise = util.getInstParamByPosition(currentInstResult, position, targetWord);
const instPortPromise = util.getInstPortByPosition(currentInstResult, position, targetWord);
@ -155,7 +155,7 @@ class VlogHoverProvider implements vscode.HoverProvider {
const paramDesc = util.makeParamDesc(paramResult);
content.appendCodeblock(paramDesc, HdlLangID.Verilog);
if (paramComment) {
content.appendCodeblock(paramComment, HdlLangID.Verilog);
content.appendMarkdown(paramComment);
}
return new vscode.Hover(content);
}
@ -170,7 +170,7 @@ class VlogHoverProvider implements vscode.HoverProvider {
content.appendCodeblock(portDesc, HdlLangID.Verilog);
if (portComment) {
content.appendCodeblock(portComment, HdlLangID.Verilog);
content.appendMarkdown(portComment);
}
return new vscode.Hover(content);
}

View File

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention */
import * as vscode from 'vscode';
import { AbsPath } from '../../../global';
import { AbsPath, LspOutput } from '../../../global';
import { HdlLangID } from '../../../global/enum';
import { hdlPath, hdlFile } from '../../../hdlFs';
import { Range } from '../../../hdlParser/common';
@ -126,12 +126,153 @@ function bin2float(bin: string, exp: number, fra: number): number | undefined {
}
}
function getFullSymbolInfoVlog(document: vscode.TextDocument, range: Range) {
const comments = [];
const currentLine = range.start.line;
const currentText = document.lineAt(currentLine).text;
// 往上找到第一个非空行
let nearestFloatLine = currentLine - 1;
while (nearestFloatLine >= 0) {
const linetext = document.lineAt(nearestFloatLine).text.trim();
if (linetext.length > 0) {
break;
}
nearestFloatLine --;
}
if (nearestFloatLine >= 0) {
const floatLineText = document.lineAt(nearestFloatLine).text.trim();
// 情况 1.1:上面的单行注释
if (floatLineText.includes('//')) {
const singleLineCommentStartIndex = floatLineText.indexOf('//');
if (singleLineCommentStartIndex === 0) {
const comment = floatLineText.substring(singleLineCommentStartIndex + 2);
if (comment !== undefined && comment.length > 0) {
comments.push(comment);
}
}
}
// 情况 1.2:上面的多行注释
if (floatLineText.includes('*/')) {
const commentEndIndex = floatLineText.indexOf('*/');
if (!floatLineText.includes('/*') || floatLineText.indexOf('/*') === 0) {
let comment = '';
for (let lineno = nearestFloatLine; lineno >= 0; -- lineno) {
const linetext = document.lineAt(lineno).text;
const commentStartIndex = linetext.indexOf('/*');
if (commentStartIndex > -1 && (lineno < nearestFloatLine || commentEndIndex > commentStartIndex)) {
let clearLineText = linetext.substring(commentStartIndex + 2).trim();
if (lineno === nearestFloatLine) {
clearLineText = clearLineText.substring(0, clearLineText.indexOf('*/'));
}
if (clearLineText.startsWith('*')) {
clearLineText = clearLineText.substring(1).trim();
}
if (clearLineText.length > 0) {
comment = clearLineText + '\n\n' + comment;
}
break;
} else {
let clearLineText = linetext.trim();
if (lineno === nearestFloatLine) {
clearLineText = clearLineText.substring(0, clearLineText.indexOf('*/'));
}
if (clearLineText.startsWith('*')) {
clearLineText = clearLineText.substring(1).trim();
}
if (clearLineText.length > 0) {
comment = clearLineText + '\n\n' + comment;
}
}
}
comment = comment.trim();
if (comment.length > 0) {
comments.push(comment);
}
}
}
}
// 情况 2.1:单行注释
if (currentText.includes('//')) {
const singleLineCommentStartIndex = currentText.indexOf('//');
const comment = currentText.substring(singleLineCommentStartIndex + 2);
if (comment !== undefined && comment.length > 0) {
comments.push(comment);
}
}
// 情况 2.2:多行注释
if (currentText.includes('/*')) {
const commentStartIndex = currentText.indexOf('/*');
let comment = '';
for (let lineno = currentLine; lineno < document.lineCount; ++ lineno) {
const linetext = document.lineAt(lineno).text;
const commentEndIndex = linetext.indexOf('*/');
if (commentEndIndex > -1 && (lineno > currentLine || commentEndIndex > commentStartIndex)) {
let clearLineText = linetext.substring(0, commentEndIndex).trim();
if (lineno === currentLine) {
clearLineText = clearLineText.substring(clearLineText.indexOf('/*') + 2).trim();
}
if (clearLineText.startsWith('*')) {
clearLineText = clearLineText.substring(1).trim();
}
comment += clearLineText + '\n';
break;
} else {
let clearLineText = linetext.trim();
if (clearLineText.startsWith('*')) {
clearLineText = clearLineText.substring(1).trim();
}
comment += clearLineText + '\n';
}
}
comment = comment.trim();
if (comment.length > 0) {
comments.push(comment);
}
}
return comments;
}
function getFullSymbolInfoVhdl() {
const comments = [];
}
async function getFullSymbolInfo(document: vscode.TextDocument, range: Range, nonblank: RegExp, l_comment_symbol: string, l_comment_regExp: RegExp): Promise<string> {
const comments = [];
if (document.languageId !== 'vhdl') {
comments.push(...getFullSymbolInfoVlog(document, range));
let resultComment = '';
for (const c of comments.reverse()) {
resultComment += c.trim() + '\n';
}
return resultComment;
}
let content = '';
let is_b_comment = false;
let line = range.start.line;
let line = range.start.line + 1;
// vscode 的行编号从 0 开始算
const firstLine = range.start.line - 1;
@ -139,6 +280,7 @@ async function getFullSymbolInfo(document: vscode.TextDocument, range: Range, no
while (line) {
line --;
content = document.lineAt(line).text;
LspOutput.report(content);
// 首先判断该行是否是空白
if (content.trim().length === 0) {

View File

@ -9,6 +9,7 @@ import { getSelectItem } from './instance';
import { ToolChainType } from '../../global/enum';
import { HdlModule } from '../../hdlParser/core';
import { Path } from '../../../resources/hdlParser';
import { ModuleDataItem } from '../treeView/tree';
interface SimulateConfig {
mod : string, // 设置的顶层模块
@ -84,7 +85,7 @@ class Simulate {
const setting = vscode.workspace.getConfiguration();
// make simulation dir
const defaultSimulationDir = hdlPath.join(opeParam.prjInfo.arch.prjPath, 'simulation', 'icarus');
const defaultSimulationDir = hdlPath.join(opeParam.prjInfo.arch.prjPath, 'icarus');
simConfig.simulationHome = setting.get('digital-ide.function.simulate.simulationHome', '');
if (!fs.existsSync(simConfig.simulationHome)) {
simConfig.simulationHome = defaultSimulationDir;
@ -357,33 +358,24 @@ class IcarusSimulate extends Simulate {
this.simulateByHdlModule(hdlModule);
}
public async simulateFile() {
const editor = vscode.window.activeTextEditor;
if (!editor) {
public async simulateFile(view: ModuleDataItem) {
if (!view.path) {
MainOutput.report('module ' + view.name + ' is not a hdlFile', ReportType.Error, true);
return;
}
const uri = editor.document.uri;
const path = hdlPath.toSlash(uri.fsPath);
const currentFile = hdlParam.getHdlFile(path);
const currentFile = hdlParam.getHdlFile(view.path);
if (!currentFile) {
MainOutput.report('path ' + path + ' is not a hdlFile', ReportType.Error, true);
MainOutput.report('path ' + view.path + ' is not a hdlFile', ReportType.Error, true);
return;
}
const items = getSelectItem(currentFile.getAllHdlModules());
if (items.length) {
let selectModule: HdlModule;
if (items.length === 1) {
selectModule = items[0].module;
} else {
const select = await vscode.window.showQuickPick(items, {placeHolder: 'choose a top module'});
if (select) {
selectModule = select.module;
} else {
return;
}
}
this.simulateByHdlModule(selectModule);
const targetModule = currentFile.getAllHdlModules().filter(mod => mod.name === view.name)[0];
if (targetModule !== undefined) {
this.simulateByHdlModule(targetModule);
} else {
MainOutput.report('There is no module named ' + view.name + ' in ' + view.path, ReportType.Error, true);
return;
}
}
}
@ -395,8 +387,8 @@ namespace Icarus {
await icarus.simulateModule(hdlModule);
}
export async function simulateFile() {
await icarus.simulateFile();
export async function simulateFile(view: ModuleDataItem) {
await icarus.simulateFile(view);
}
};

View File

@ -200,9 +200,18 @@ class ToolTreeProvider extends BaseCommandTreeProvider {
// remove prjPath & .xil
const prjPath = opeParam.prjInfo.arch.prjPath;
const xilFolder = hdlPath.join(workspacePath, '.Xil');
hdlDir.rmdir(prjPath);
hdlDir.rmdir(xilFolder);
if (prjPath !== opeParam.workspacePath) {
hdlDir.rmdir(prjPath);
hdlDir.rmdir(xilFolder);
MainOutput.report("remove dir : " + prjPath);
MainOutput.report("remove dir : " + xilFolder);
} else {
vscode.window.showWarningMessage("arch.prjPath is the same as the workspace path, the clean will delete the project, please check your arch.prjPath!");
}
// move bd * ip
const plName = opeParam.prjInfo.prjName.PL;
@ -211,13 +220,16 @@ class ToolTreeProvider extends BaseCommandTreeProvider {
const sourceBdPath = `${workspacePath}/prj/xilinx/${plName}.srcs/sources_1/bd`;
hdlDir.mvdir(sourceIpPath, targetPath, true);
MainOutput.report("move dir from " + sourceIpPath + " to " + targetPath);
hdlDir.mvdir(sourceBdPath, targetPath, true);
MainOutput.report("move dir from " + sourceBdPath + " to " + targetPath);
const ignores = hdlIgnore.getIgnoreFiles();
const strFiles = hdlFile.pickFileRecursive(workspacePath, ignores, p => p.endsWith('.str'));
for (const path of strFiles) {
hdlFile.removeFile(path);
MainOutput.report("remove file " + path);
}
const logFiles = hdlFile.pickFileRecursive(workspacePath, ignores, p => p.endsWith('.log'));

View File

@ -14,7 +14,7 @@ interface ModuleDataItem {
icon: string, // 图标
name: string, // module name
type: string,
range: Range | null,
range: Range | undefined | null,
path: AbsPath | undefined, // path of the file
parent: ModuleDataItem | null // parent file
}
@ -219,12 +219,13 @@ class ModuleTreeProvider implements vscode.TreeDataProvider<ModuleDataItem> {
if (targetModule) {
for (const instance of targetModule.getAllInstances()) {
// 所有的例化模块都定向到它的定义文件上
const item: ModuleDataItem = {
icon: 'file',
type: instance.name,
name: instance.type,
range: instance.range,
path: instance.parentMod.path,
range: instance.module?.range,
path: instance.module?.path,
parent: element
};

View File

@ -9,6 +9,8 @@ import { ToolChainType, LibraryState, XilinxIP,
import { PrjInfoSchema } from './propertySchema';
import assert = require('assert');
import * as hdlPath from '../hdlFs/path';
import { hdlDir } from '../hdlFs';
import { MainOutput } from './outputChannel';
type AbsPath = string;
@ -265,7 +267,9 @@ class PrjInfo implements PrjInfoMeta {
if (fs.existsSync(uniformPath)) {
return uniformPath;
} else {
vscode.window.showErrorMessage('path ' + uniformPath + ' not exist!');
hdlDir.mkdir(uniformPath);
MainOutput.report("create dir: " + uniformPath);
// vscode.window.showErrorMessage('path ' + uniformPath + ' not exist!');
return undefined;
}
} else {

View File

@ -7,6 +7,7 @@ import { PrjInfo, RawPrjInfo } from '../global/prjInfo';
import { HdlLangID } from '../global/enum';
import { hdlFile, hdlPath } from '../hdlFs';
import { getIconConfig } from '../hdlFs/icons';
import { getLanguageId } from '../hdlFs/file';
type MissPathType = { path?: string };
type LibPickItem = vscode.QuickPickItem & MissPathType;
@ -76,14 +77,14 @@ class LibPick {
}
private getReadmeText(path: AbsPath, fileName: string): string | undefined {
const mdPath1 = hdlPath.join(path, fileName, 'readme.md');
if (fs.existsSync(mdPath1)) {
return hdlFile.readFile(mdPath1);
}
const mdPath2 = hdlPath.join(path, fileName, 'README.md');
if (fs.existsSync(mdPath2)) {
return hdlFile.readFile(mdPath2);
const allowReadmeFile = ['readme.md', 'README.md', 'readme', 'README', 'readme.txt']
for (const readmeFile of allowReadmeFile) {
const mdpath = hdlPath.join(path, fileName, readmeFile);
if (fs.existsSync(mdpath)) {
return hdlFile.readFile(mdpath);
}
}
return undefined;
}
@ -98,12 +99,30 @@ class LibPick {
for (const fileName of fs.readdirSync(path)) {
const filePath = hdlPath.join(path, fileName);
const themeIcon = this.getPathIcon(filePath);
const label = themeIcon + " " + fileName;
const mdText = this.getReadmeText(path, fileName);
const description = mdText ? mdText : '';
const buttons = [{iconPath: getIconConfig('import'), tooltip: 'import everything in ' + fileName}];
items.push({label, description, path: filePath, buttons});
if (hdlFile.isFile(filePath)) {
const fileLangId = getLanguageId(filePath);
if (fileLangId === HdlLangID.Unknown) {
// 不是 hdl 直接跳过
continue;
}
const themeIcon = this.getPathIcon(filePath);
const label = themeIcon + " " + fileName;
const buttons = [{iconPath: getIconConfig('import'), tooltip: 'import everything in ' + fileName}];
items.push({label, description: '', path: filePath, buttons});
} else if (hdlFile.isDir(filePath)) {
if (['.git', '.github', '.vscode'].includes(fileName)) {
continue;
}
const themeIcon = this.getPathIcon(filePath);
const label = themeIcon + " " + fileName;
// 寻找 fileName 下的 readmefileName 在这里是一个 文件夹
const mdText = this.getReadmeText(path, fileName);
const description = mdText ? mdText : '';
const buttons = [{iconPath: getIconConfig('import'), tooltip: 'import everything in ' + fileName}];
items.push({label, description, path: filePath, buttons});
}
}
return items;
}