diff --git a/l10n/bundle.l10n.de.json b/l10n/bundle.l10n.de.json index 2f8ea39..cef3074 100644 --- a/l10n/bundle.l10n.de.json +++ b/l10n/bundle.l10n.de.json @@ -61,5 +61,13 @@ "info.dide-doc.source.cannot-find": "Nicht gefunden", "info.command.instantiation.pick-title": "Select a Module", "warn.command.clean.prjPath-is-workspace": "arch.prjPath is the same as the workspace path, the clean will delete the project, please check your arch.prjPath!", - "info.monitor.ppy.impl-change-to-project": "Änderungen werden auf das {0}-Projekt angewendet" + "info.monitor.ppy.impl-change-to-project": "Änderungen werden auf das {0}-Projekt angewendet", + "info.initialise.report.title": "Analyse von {0} HDL-Dateien abgeschlossen, {1} ungelöste Instanzmodule gefunden", + "info.launch.following-folder-tracked": "Die Dateien im folgenden Ordner werden kontinuierlich analysiert und vollständige LSP-Dienste bereitgestellt.", + "info.launch.search-and-parse": "Suche und analysiere HDL-Dateien aus dem untenstehenden Pfad", + "info.launch.digital-ide-current-version": "Digital-IDE wurde gestartet, aktuelle Version:", + "info.pl.xilinx.update-addfiles": "Datei zu Xilinx-Projekt hinzufügen", + "info.pl.xilinx.update-delfiles": "Löschen Sie die folgenden Dateien aus dem Xilinx-Projekt.", + "info.pl.xilinx.no-need-add-files": "Keine Dateien zum Hinzufügen zum Xilinx-Projekt", + "info.pl.xilinx.no-need-del-files": "Es müssen keine Dateien aus Xilinx gelöscht werden." } \ No newline at end of file diff --git a/l10n/bundle.l10n.en.json b/l10n/bundle.l10n.en.json index 834d8dc..1632f95 100644 --- a/l10n/bundle.l10n.en.json +++ b/l10n/bundle.l10n.en.json @@ -61,5 +61,13 @@ "info.dide-doc.source.cannot-find": "Cannot find", "info.command.instantiation.pick-title": "Select a Module", "warn.command.clean.prjPath-is-workspace": "arch.prjPath is the same as the workspace path, the clean will delete the project, please check your arch.prjPath!", - "info.monitor.ppy.impl-change-to-project": "Applying changes to the {0} project" + "info.monitor.ppy.impl-change-to-project": "Applying changes to the {0} project", + "info.initialise.report.title": "Completed parsing {0} HDL files, found {1} unresolved instantiation modules", + "info.launch.following-folder-tracked": "The files in the folder below will be continuously parsed and full LSP services will be provided.", + "info.launch.search-and-parse": "Search and parse HDL files from the path below", + "info.launch.digital-ide-current-version": "Digital-IDE has been launched, current version:", + "info.pl.xilinx.update-addfiles": "Add file to Xilinx project", + "info.pl.xilinx.update-delfiles": "Delete the following files from the Xilinx project.", + "info.pl.xilinx.no-need-add-files": "No files need to be added to the Xilinx project", + "info.pl.xilinx.no-need-del-files": "There are no files to be deleted from Xilinx." } \ No newline at end of file diff --git a/l10n/bundle.l10n.ja.json b/l10n/bundle.l10n.ja.json index f0e233f..4c4ad8d 100644 --- a/l10n/bundle.l10n.ja.json +++ b/l10n/bundle.l10n.ja.json @@ -61,5 +61,13 @@ "info.dide-doc.source.cannot-find": "見つかりません", "info.command.instantiation.pick-title": "Select a Module", "warn.command.clean.prjPath-is-workspace": "arch.prjPath is the same as the workspace path, the clean will delete the project, please check your arch.prjPath!", - "info.monitor.ppy.impl-change-to-project": "{0} プロジェクトに変更を適用しています" + "info.monitor.ppy.impl-change-to-project": "{0} プロジェクトに変更を適用しています", + "info.initialise.report.title": "{0} 個のHDLファイルの解析が完了し、{1} 個の未解決のインスタンスモジュールが見つかりました", + "info.launch.following-folder-tracked": "以下のフォルダ内のファイルは継続的に解析され、完全なLSPサービスが提供されます。", + "info.launch.search-and-parse": "以下のパスからHDLファイルを検索して解析します", + "info.launch.digital-ide-current-version": "Digital-IDEが起動しました、現在のバージョン:", + "info.pl.xilinx.update-addfiles": "ファイルを Xilinx プロジェクトに追加", + "info.pl.xilinx.update-delfiles": "以下のファイルをXilinxプロジェクトから削除してください。", + "info.pl.xilinx.no-need-add-files": "Xilinx プロジェクトに追加するファイルはありません", + "info.pl.xilinx.no-need-del-files": "Xilinx から削除するファイルはありません。" } \ No newline at end of file diff --git a/l10n/bundle.l10n.zh-cn.json b/l10n/bundle.l10n.zh-cn.json index 151b742..48a6b93 100644 --- a/l10n/bundle.l10n.zh-cn.json +++ b/l10n/bundle.l10n.zh-cn.json @@ -61,5 +61,13 @@ "info.dide-doc.source.cannot-find": "无法找到", "info.command.instantiation.pick-title": "选择一个模块", "warn.command.clean.prjPath-is-workspace": "arch.prjPath 和当前的工作区目录相同, clean 功能可能会删除整个项目,请检查你的 arch.prjPath !", - "info.monitor.ppy.impl-change-to-project": "正在将修改应用于 {0} 项目中" + "info.monitor.ppy.impl-change-to-project": "正在将修改应用于 {0} 项目中", + "info.initialise.report.title": "完成 {0} 个 HDL 文件的解析,发现 {1} 个未解决的例化模块", + "info.launch.following-folder-tracked": "下方文件夹中的文件将被持续解析并提供完整的 LSP 服务", + "info.launch.search-and-parse": "从下方路径中搜索并解析 HDL 文件", + "info.launch.digital-ide-current-version": "Digital-IDE 已经启动,当前版本:", + "info.pl.xilinx.update-addfiles": "添加文件到 Xilinx 工程", + "info.pl.xilinx.update-delfiles": "将下方文件从 Xilinx 工程中删除", + "info.pl.xilinx.no-need-add-files": "没有需要添加到 Xilinx 工程的文件", + "info.pl.xilinx.no-need-del-files": "没有需要从 Xilinx 中删除的文件" } \ No newline at end of file diff --git a/l10n/bundle.l10n.zh-tw.json b/l10n/bundle.l10n.zh-tw.json index 735d963..40f6f5b 100644 --- a/l10n/bundle.l10n.zh-tw.json +++ b/l10n/bundle.l10n.zh-tw.json @@ -61,5 +61,13 @@ "info.dide-doc.source.cannot-find": "無法找到", "info.command.instantiation.pick-title": "Select a Module", "warn.command.clean.prjPath-is-workspace": "arch.prjPath is the same as the workspace path, the clean will delete the project, please check your arch.prjPath!", - "info.monitor.ppy.impl-change-to-project": "正在將修改應用於 {0} 專案中" + "info.monitor.ppy.impl-change-to-project": "正在將修改應用於 {0} 專案中", + "info.initialise.report.title": "完成 {0} 個 HDL 檔案的解析,發現 {1} 個未解決的例化模組", + "info.launch.following-folder-tracked": "下方資料夾中的檔案將被持續解析並提供完整的LSP服務。", + "info.launch.search-and-parse": "從下方路徑中搜尋並解析 HDL 檔案", + "info.launch.digital-ide-current-version": "Digital-IDE 已啟動,目前版本:", + "info.pl.xilinx.update-addfiles": "將檔案新增到 Xilinx 專案", + "info.pl.xilinx.update-delfiles": "從 Xilinx 專案中刪除以下檔案。", + "info.pl.xilinx.no-need-add-files": "沒有需要添加到 Xilinx 工程的文件", + "info.pl.xilinx.no-need-del-files": "沒有需要從 Xilinx 中刪除的檔案。" } \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index e2d7adc..e536ed7 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -39,8 +39,10 @@ async function launch(context: vscode.ExtensionContext) { initialiseI18n(context); console.log(t('info.welcome.title')); - console.log(t('info.welcome.join-qq-group') + ' https://qm.qq.com/q/1M655h3GsA'); + console.log(t('info.welcome.join-qq-group') + ' https://qm.qq.com/q/1M655h3GsA'); + const packageJson = readPackageJson(context); + MainOutput.report(t('info.launch.digital-ide-current-version') + packageJson.version, ReportType.Launch); if (packageJson === undefined) { return; @@ -60,7 +62,6 @@ async function launch(context: vscode.ExtensionContext) { // 初始化 OpeParam // 包含基本的插件的文件系统信息、用户配置文件和系统配置文件的合并数据结构 const refreshPrjConfig = await manager.prjManage.initOpeParam(context); - MainOutput.report('finish initialise opeParam', ReportType.Info); manager.prjManage.refreshPrjFolder(refreshPrjConfig); }); @@ -88,7 +89,6 @@ async function launch(context: vscode.ExtensionContext) { }); - MainOutput.report('Digital-IDE 已经启动,当前版本:' + packageJson.version, ReportType.Launch); console.log(hdlParam); // show welcome information (if first install) diff --git a/src/function/lsp/completion/tcl.ts b/src/function/lsp/completion/tcl.ts index 3447fec..24fbf7f 100644 --- a/src/function/lsp/completion/tcl.ts +++ b/src/function/lsp/completion/tcl.ts @@ -8,7 +8,6 @@ class TCLCompletionProvider implements vscode.CompletionItemProvider { keywordsCompletionItems: vscode.CompletionItem[] | undefined; constructor() { this.keywordsCompletionItems = this.provideKeywords(); - MainOutput.report('lsp for tcl is ready'); } public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext): vscode.ProviderResult> { try { @@ -28,7 +27,6 @@ class TCLCompletionProvider implements vscode.CompletionItemProvider { keywords.push(item); } this.keywordsCompletionItems = keywords; - MainOutput.report('tcl lsp is ready'); } return this.keywordsCompletionItems; diff --git a/src/hdlParser/core.ts b/src/hdlParser/core.ts index 2fad1a2..f1c1b05 100644 --- a/src/hdlParser/core.ts +++ b/src/hdlParser/core.ts @@ -196,13 +196,33 @@ class HdlParam { return this.unhandleInstances.size; } - public getUnhandleInstanceByType(typeName: string): HdlInstance | undefined { + /** + * @description 获取所有 scope 内存在 unhandle instance 的 module + */ + public getAllUnhandleInstanceBelongedModule(): HdlModule[] { + const modules = new Set(); + for (const instance of this.unhandleInstances) { + modules.add(instance.parentMod); + } + return [...modules]; + } + + /** + * @description 输入 moduleName,找到这个 module 的所有置于 unhandleInstances 中的例化,并去 solve 它们 + * 因为一个 module 对应的 unsolved instance 可能不止一个。比如现在项目中,有两个地方存在 AGC 模块的例化, + * 但是当前项目并没有引入 AGC 的 module 申明,那么当引入 AGC 后,外部就应该调用 getUnhandleInstancesByModuleName("AGC") + * 并返回两个 AGC 的例化模块,然后去 solve 它们 + * @param moduleName + * @returns + */ + public getUnhandleInstancesByModuleName(moduleName: string): HdlInstance[] { + const unsolvedInstances = []; for (const inst of this.unhandleInstances) { - if (inst.type === typeName) { - return inst; + if (inst.type === moduleName) { + unsolvedInstances.push(inst); } } - return undefined; + return unsolvedInstances; } public addUnhandleInstance(inst: HdlInstance) { @@ -213,21 +233,6 @@ class HdlParam { this.unhandleInstances.delete(inst); } - /** - * vlog -> HdlLangID.Verilog - * svlog -> HdlLangID.SystemVerilog - * vhdl -> HdlLangID.Vhdl - * @param langID - */ - private alignLanguageId(langID: string) : HdlLangID { - switch (langID) { - case 'vhdl': return HdlLangID.Vhdl; - case 'vlog': return HdlLangID.Verilog; - case 'svlog': return HdlLangID.SystemVerilog; - default: return HdlLangID.Unknown; - } - } - private async doHdlFast(path: AbsPath, fileType: DoFastFileType) { try { const fast = await HdlSymbol.fast(path, fileType); @@ -383,15 +388,21 @@ class HdlParam { } } + /** + * @description 往 hdlparam 中添加路径中的若干模块 + * @param path + */ public async addHdlFile(path: AbsPath) { path = hdlPath.toSlash(path); + // 解析并构建 await this.doHdlFast(path, 'common'); + // 初始化 const moduleFile = this.getHdlFile(path); if (!moduleFile) { MainOutput.report('error happen when create moduleFile ' + path, ReportType.Warn); } else { moduleFile.makeInstance(); - for (const module of moduleFile.getAllHdlModules()) { + for (const module of moduleFile.getAllHdlModules()) { module.solveUnhandleInstance(); } } @@ -480,10 +491,11 @@ class HdlInstance { // add refer for module this.module?.addGlobalReferedInstance(this); // if module and parent module share the same source (e.g both in src folder) - if (this.isSameSource()) { + if (this.isSameSourceInstantiation()) { + // 增加当前 instance 的引用,并从对应类型的顶层模块中剔除 this.module?.addLocalReferedInstance(this); } - } else { + } else { doPrimitivesJudgeApi(instModName).then(isPrimitive => { if (isPrimitive) { // 构造 fake hdlfile @@ -497,15 +509,18 @@ class HdlInstance { } } + /** - * judge if the instance is a cross source reference - * e.g. this.module is from src, this.parentMod is from sim, then - * isSameSource will return false, meaning that the instance is a cross source reference + * @description 判断当前的 `instance` 对应的例化行为是否为一个同源例化 (SSI, same source instantiation) * - * a cross source reference won't affect the top module reference of this.module, - * meaning that a top module in one source can have its instance in other source + * 对于标准项目结构,也就是 src + sim ,如果在 moduleA 中完成了 moduleB 的例化,且 moduleA 和 moduleB 都是 src 文件夹下的, + * 那么这个例化就是一个同源例化;如果 moduleB 在 sim 下, moduleA 在 src 下,那么当前的例化就是一个非同源例化。 + * + * 同源例化造成的引用为 local ref,非同源例化 + 同源例化造成的引用为 global ref。在模块树下, src 文件夹下的只有 local ref 为空的 module 才是顶层模块 + * 换句话说,非同源例化一定不会造成顶层模块的变化,但是同源例化有可能会。 + * @returns */ - public isSameSource(): boolean { + public isSameSourceInstantiation(): boolean { const parentMod = this.parentMod; const instMod = this.module; if (instMod) { @@ -692,7 +707,7 @@ class HdlModule { const instMod = inst.module; if (instMod) { instMod.deleteGlobalReferedInstance(inst); - if (inst.isSameSource()) { + if (inst.isSameSourceInstantiation()) { instMod.deleteLocalReferedInstance(inst); } } @@ -796,7 +811,9 @@ class HdlModule { } public solveInstModPathStatus(): common.InstModPathStatus { - const inst = hdlParam.getUnhandleInstanceByType(this.name); + // TODO: 修改这套系统,因为现在只是拿第一个例化来判断的,这是不合理的 + // 应该把 common.InstModPathStatus 修改成一个可以通过析取来表示的变量 + const inst = hdlParam.getUnhandleInstancesByModuleName(this.name)[0]; if (!inst) { return common.InstModPathStatus.Unknown; } @@ -815,24 +832,25 @@ class HdlModule { } } + /** + * @description 从全局寻找这个 module 的例化,并尝试修改它的状态 + */ public solveUnhandleInstance() { - const inst = hdlParam.getUnhandleInstanceByType(this.name); + const instances = hdlParam.getUnhandleInstancesByModuleName(this.name); - if (inst) { - const userModule = inst.parentMod; - // match a inst with the same type name of the module - // remove from unhandle list - hdlParam.deleteUnhandleInstance(inst); - userModule.deleteUnhandleInstance(inst); + for (const instance of instances) { + const belongScopeModule = instance.parentMod; + // 先从 unsolved 堆中删除当前的 instance + hdlParam.deleteUnhandleInstance(instance); + belongScopeModule.deleteUnhandleInstance(instance); - // assign instModPath - inst.instModPath = this.path; + // 解决 + instance.instModPath = this.path; + instance.instModPathStatus = this.solveInstModPathStatus(); - // judge the type of instModPathStatus - inst.instModPathStatus = this.solveInstModPathStatus(); - - // assign module in the instance - inst.locateHdlModule(); + // 找寻这个 instance 对应的真正的 module(也有可能是原语) + // 并将这个 instance 加入这个 module 的计数器中 + instance.locateHdlModule(); } } diff --git a/src/manager/prj.ts b/src/manager/prj.ts index 91aefdf..0b5303e 100644 --- a/src/manager/prj.ts +++ b/src/manager/prj.ts @@ -113,8 +113,8 @@ class PrjManage { // 如果是单文件模式,需要的操作 } else { // 先处理 lib 文件 - const fileChange = await libManage.processLibFiles(prjInfo.library); - MainOutput.report(`libManage finish process, add ${fileChange.add.length} files, del ${fileChange.del.length} files`, ReportType.Info); + // const fileChange = await libManage.processLibFiles(prjInfo.library); + // MainOutput.report(`libManage finish process, add ${fileChange.add.length} files, del ${fileChange.del.length} files`, ReportType.Info); // 默认搜索路径包括: // src, sim, lib @@ -125,8 +125,8 @@ class PrjManage { searchPathSet.checkAdd(prjInfo.getLibraryCustomPaths()); } - MainOutput.report(' search folders: ', ReportType.Debug); - searchPathSet.files.forEach(p => MainOutput.report(p, ReportType.Debug)); + const reportMsg = ['', ... searchPathSet.files].join('\n\t'); + MainOutput.report(t('info.launch.search-and-parse') + reportMsg, ReportType.Run); // TODO : make something like .gitignore const ignores = hdlIgnore.getIgnoreFiles(); @@ -199,15 +199,13 @@ class PrjManage { // 分析依赖关系错位情况 const unhandleNum = hdlParam.getUnhandleInstanceNumber(); - MainOutput.report(`finish analyse ${hdlFiles.length} hdl files, find ${unhandleNum} unsolved instances`, ReportType.Info); - + const reportMsg = t('info.initialise.report.title', hdlFiles.length.toString(), unhandleNum.toString()); + MainOutput.report(reportMsg, ReportType.Launch); this.pl = new PlManage(); // TODO : finish it later // this.ps = new PsManage(); - MainOutput.report('create pl', ReportType.Info); - if (countTimeCost) { console.timeLog('launch'); } diff --git a/src/monitor/event.ts b/src/monitor/event.ts index 7f910a9..2f53416 100644 --- a/src/monitor/event.ts +++ b/src/monitor/event.ts @@ -309,14 +309,31 @@ class PpyAction extends BaseAction { hdlParam.deleteHdlFile(path); } - // TODO: 增加解决 instance 的地方 + // 判断新加入的 module 是否还是顶层模块 } + public async updatePL(addFiles: AbsPath[], delFiles: AbsPath[]) { // current only support xilinx if (prjManage.pl) { - await prjManage.pl.addFiles(addFiles); - await prjManage.pl.delFiles(delFiles); + const addfileActionTag = '(add files) '; + const delfileActionTag = '(del files) '; + if (addFiles.length > 0) { + const reportMsg = ['', ...addFiles].join('\n\t'); + MainOutput.report(addfileActionTag + t('info.pl.xilinx.update-addfiles') + reportMsg, ReportType.Run); + await prjManage.pl.addFiles(addFiles); + } else { + MainOutput.report(addfileActionTag + t('info.pl.xilinx.no-need-add-files')); + } + + if (delFiles.length > 0) { + const reportMsg = ['', ...delFiles].join('\n\t'); + MainOutput.report(delfileActionTag + t('info.pl.xilinx.update-delfiles') + reportMsg, ReportType.Run); + await prjManage.pl.delFiles(delFiles); + } else { + MainOutput.report(delfileActionTag + t('info.pl.xilinx.no-need-del-files')); + } + } else { MainOutput.report('PL is not registered', ReportType.Warn); } diff --git a/src/monitor/index.ts b/src/monitor/index.ts index 96bbb76..c389986 100644 --- a/src/monitor/index.ts +++ b/src/monitor/index.ts @@ -5,6 +5,7 @@ import { PathSet } from '../global/util'; import { hdlPath } from '../hdlFs'; import * as Event from './event'; +import { t } from '../i18n'; class HdlMonitor{ private monitorConfig: chokidar.WatchOptions; @@ -53,8 +54,9 @@ class HdlMonitor{ const globPath = hdlPath.join(folder, hdlExtsGlob); monitorFoldersWithGlob.push(globPath); } - MainOutput.report('Following folders are tracked: '); - monitorPathSet.files.forEach(p => MainOutput.report(p)); + + const reportString = ['', ...monitorPathSet.files].join('\n\t'); + MainOutput.report(t('info.launch.following-folder-tracked') + reportString, ReportType.Launch); return this.makeMonitor(monitorFoldersWithGlob); }