0.4.0 第三次测试迭代
This commit is contained in:
parent
a141f5f53c
commit
ab24f6c670
@ -71,5 +71,12 @@
|
||||
"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.",
|
||||
"error.pl.launch.not-valid-vivado-path": "Fehler beim Starten des Vivado TCL-Skriptinterpreters: {0}. Bitte überprüfen Sie, ob der Startpfad für Vivado korrekt ist. Derzeit eingestellter Startordnerpfad für Vivado: {1}",
|
||||
"info.pl.launch.set-vivado-path": "Zur Einstellung des Vivado-Installationspfads gehen"
|
||||
"info.pl.launch.set-vivado-path": "Zur Einstellung des Vivado-Installationspfads gehen",
|
||||
"info.monitor.current-mode": "Aktueller Monitor-Modus: {0}",
|
||||
"info.simulation.create-vvp": "VVP-Datei in {0} erstellen",
|
||||
"error.simulation.reason": "Grund: {0}",
|
||||
"info.simulate.vvp.vcd-generate": "vcd-Datei wurde erstellt in {0}",
|
||||
"error.simluate.icarus.use-primitives": "Es wurde ein Primitiv {0} erkannt, aber Icarus iverilog unterstützt keine Primitiven.",
|
||||
"error.simluate.icarus.use-ip": "Es wurde die IP {0} verwendet, aber Icarus iverilog unterstützt keine IP.",
|
||||
"error.simulation.error-happen-run-command": "Fehler bei der Icarus-Simulation:"
|
||||
}
|
@ -71,5 +71,12 @@
|
||||
"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.",
|
||||
"error.pl.launch.not-valid-vivado-path": "Error encountered while starting the Vivado TCL script interpreter: {0}. Please check if your Vivado startup path is correct. Currently set Vivado startup folder path: {1}",
|
||||
"info.pl.launch.set-vivado-path": "Go to set the Vivado installation path"
|
||||
"info.pl.launch.set-vivado-path": "Go to set the Vivado installation path",
|
||||
"info.monitor.current-mode": "Current monitor mode: {0}",
|
||||
"info.simulation.create-vvp": "Create VVP file in {0}",
|
||||
"error.simulation.reason": "Reason: {0}",
|
||||
"info.simulate.vvp.vcd-generate": "vcd file has been generated to {0}",
|
||||
"error.simluate.icarus.use-primitives": "Primitive {0} detected, but Icarus iverilog does not support primitives.",
|
||||
"error.simluate.icarus.use-ip": "Detected the use of IP {0}, but Icarus iverilog does not support IP.",
|
||||
"error.simulation.error-happen-run-command": "Error during Icarus simulation:"
|
||||
}
|
@ -71,5 +71,12 @@
|
||||
"info.pl.xilinx.no-need-add-files": "Xilinx プロジェクトに追加するファイルはありません",
|
||||
"info.pl.xilinx.no-need-del-files": "Xilinx から削除するファイルはありません。",
|
||||
"error.pl.launch.not-valid-vivado-path": "Vivado TCL スクリプトインタプリタの起動中にエラーが発生しました:{0}。Vivado の起動パスが正しいか確認してください。現在設定されている Vivado 起動フォルダパス:{1}",
|
||||
"info.pl.launch.set-vivado-path": "Vivado インストールパスの設定に移動"
|
||||
"info.pl.launch.set-vivado-path": "Vivado インストールパスの設定に移動",
|
||||
"info.monitor.current-mode": "現在のモニターモード:{0}",
|
||||
"info.simulation.create-vvp": "{0} で VVP ファイルを作成",
|
||||
"error.simulation.reason": "理由: {0}",
|
||||
"info.simulate.vvp.vcd-generate": "vcdファイルが生成されました: {0}",
|
||||
"error.simluate.icarus.use-primitives": "プリミティブ {0} が検出されましたが、Icarus iverilog はプリミティブをサポートしていません。",
|
||||
"error.simluate.icarus.use-ip": "IP {0} が使用されていますが、Icarus iverilog は IP をサポートしていません。",
|
||||
"error.simulation.error-happen-run-command": "Icarusシミュレーション中にエラーが発生しました:"
|
||||
}
|
@ -71,5 +71,12 @@
|
||||
"info.pl.xilinx.no-need-add-files": "没有需要添加到 Xilinx 工程的文件",
|
||||
"info.pl.xilinx.no-need-del-files": "没有需要从 Xilinx 中删除的文件",
|
||||
"error.pl.launch.not-valid-vivado-path": "启动 Vivado TCL 脚本解释器遇到错误:{0} 。请检查你的 Vivado 启动路径是否正确,当前设置的 Vivado 启动文件夹路径:{1}",
|
||||
"info.pl.launch.set-vivado-path": "前往设置 Vivado 安装路径"
|
||||
"info.pl.launch.set-vivado-path": "前往设置 Vivado 安装路径",
|
||||
"info.monitor.current-mode": "当前监视器模式:{0}",
|
||||
"info.simulation.create-vvp": "在 {0} 创建 VVP 文件",
|
||||
"error.simulation.reason": "原因: {0}",
|
||||
"info.simulate.vvp.vcd-generate": "vcd 文件已经生成至 {0}",
|
||||
"error.simluate.icarus.use-primitives": "检测到使用了原语 {0},但是 Icarus iverilog 并不支持原语",
|
||||
"error.simluate.icarus.use-ip": "检测到使用了 IP {0},但是 Icarus iverilog 并不支持 IP",
|
||||
"error.simulation.error-happen-run-command": "Icarus 仿真时,出现错误:"
|
||||
}
|
@ -71,5 +71,12 @@
|
||||
"info.pl.xilinx.no-need-add-files": "沒有需要添加到 Xilinx 工程的文件",
|
||||
"info.pl.xilinx.no-need-del-files": "沒有需要從 Xilinx 中刪除的檔案。",
|
||||
"error.pl.launch.not-valid-vivado-path": "啟動 Vivado TCL 腳本解釋器遇到錯誤:{0} 。請檢查你的 Vivado 啟動路徑是否正確,目前設定的 Vivado 啟動資料夾路徑:{1}",
|
||||
"info.pl.launch.set-vivado-path": "前往設定 Vivado 安裝路徑"
|
||||
"info.pl.launch.set-vivado-path": "前往設定 Vivado 安裝路徑",
|
||||
"info.monitor.current-mode": "目前監視器模式:{0}",
|
||||
"info.simulation.create-vvp": "在 {0} 建立 VVP 檔案",
|
||||
"error.simulation.reason": "原因: {0}",
|
||||
"info.simulate.vvp.vcd-generate": "vcd 檔案已生成至 {0}",
|
||||
"error.simluate.icarus.use-primitives": "偵測到使用了原語 {0},但是 Icarus iverilog 並不支援原語。",
|
||||
"error.simluate.icarus.use-ip": "偵測到使用了 IP {0},但是 Icarus iverilog 並不支援 IP。",
|
||||
"error.simulation.error-happen-run-command": "Icarus 模擬時,出現錯誤:"
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import * as fspath from 'path';
|
||||
import * as child_process from 'child_process';
|
||||
|
||||
import { hdlParam } from '../../hdlParser';
|
||||
@ -10,6 +11,7 @@ import { HdlLangID, ToolChainType } from '../../global/enum';
|
||||
import { HdlFile, HdlModule } from '../../hdlParser/core';
|
||||
import { ModuleDataItem } from '../treeView/tree';
|
||||
import { defaultMacro, doFastApi } from '../../hdlParser/util';
|
||||
import { t } from '../../i18n';
|
||||
|
||||
type Path = string;
|
||||
|
||||
@ -185,17 +187,35 @@ class IcarusSimulate extends Simulate {
|
||||
return args.join(' ').trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 生成用于进行仿真的依赖项相关的参数
|
||||
* @param dependences
|
||||
* @returns
|
||||
*/
|
||||
private makeDependenceArguments(dependences: string[]): string {
|
||||
// 去重
|
||||
const visitedPath = new Set<Path>;
|
||||
const args = [];
|
||||
for (const dep of dependences) {
|
||||
// 去重
|
||||
if (visitedPath.has(dep)) {
|
||||
continue;
|
||||
}
|
||||
// icarus 不支持 原语
|
||||
if (dep === 'xilinx-primitives') {
|
||||
MainOutput.report(t('error.simluate.icarus.use-primitives', dep), { level: ReportType.Error });
|
||||
continue;
|
||||
}
|
||||
// icarus 不支持 IP
|
||||
if (dep.startsWith(opeParam.prjInfo.ipPath)) {
|
||||
MainOutput.report(t('error.simluate.icarus.use-ip', dep), { level: ReportType.Error });
|
||||
continue;
|
||||
}
|
||||
|
||||
args.push(makeSafeArgPath(dep));
|
||||
visitedPath.add(dep);
|
||||
}
|
||||
|
||||
return args.join(' ').trim();
|
||||
}
|
||||
|
||||
@ -215,13 +235,15 @@ class IcarusSimulate extends Simulate {
|
||||
}
|
||||
|
||||
/**
|
||||
* generate acutal iverlog simulation command
|
||||
* @description 获取 iverilog 仿真的命令
|
||||
* @param name name of top module
|
||||
* @param path path of the simulated file
|
||||
* @param dependences dependence that not specified in `include macro
|
||||
* @returns
|
||||
*/
|
||||
private getCommand(name: string, path: AbsPath, dependences: string[]): string | undefined {
|
||||
MainOutput.clear();
|
||||
|
||||
const simConfig = this.getConfig(path, 'iverilog');
|
||||
if (!simConfig) {
|
||||
return;
|
||||
@ -252,22 +274,14 @@ class IcarusSimulate extends Simulate {
|
||||
const iverilogPath = simConfig.iverilogPath;
|
||||
// default is -g2012
|
||||
const argu = '-g' + iverilogCompileOptions.standard;
|
||||
const outVvpPath = makeSafeArgPath(hdlPath.join(simConfig.simulationHome, 'out.vvp'));
|
||||
const outVvpPath = makeSafeArgPath(hdlPath.join(simConfig.simulationHome, name + '.vvp'));
|
||||
const mainPath = makeSafeArgPath(path);
|
||||
|
||||
// console.log(macroIncludeArgs);
|
||||
// console.log(thirdLibraryDirArgs);
|
||||
// console.log(dependenceArgs);
|
||||
// console.log(thirdLibraryFileArgs);
|
||||
|
||||
const cmd = `${iverilogPath} ${argu} -o ${outVvpPath} -s ${name} ${macroIncludeArgs} ${thirdLibraryDirArgs} ${mainPath} ${dependenceArgs} ${thirdLibraryFileArgs}`;
|
||||
MainOutput.report(cmd, {
|
||||
level: ReportType.Run
|
||||
});
|
||||
return cmd;
|
||||
}
|
||||
|
||||
private execInTerminal(command: string, cwd: AbsPath) {
|
||||
private execInTerminal(command: string, cwd: AbsPath, hdlModule: HdlModule) {
|
||||
// let vvp: vscode.Terminal;
|
||||
// const targetTerminals = vscode.window.terminals.filter(t => t.name === 'vvp');
|
||||
// if (targetTerminals.length > 0) {
|
||||
@ -291,56 +305,136 @@ class IcarusSimulate extends Simulate {
|
||||
// }
|
||||
}
|
||||
|
||||
private execInOutput(command: string, cwd: AbsPath) {
|
||||
/**
|
||||
* @description 在 Digital IDE 窗口中运行 iverilog 的快速仿真
|
||||
* @param command
|
||||
* @param cwd
|
||||
* @param hdlModule
|
||||
* @returns
|
||||
*/
|
||||
private execInOutput(command: string, cwd: AbsPath, hdlModule: HdlModule) {
|
||||
const simConfig = this.simConfig;
|
||||
if (!simConfig) {
|
||||
return;
|
||||
}
|
||||
child_process.exec(command, { cwd }, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
MainOutput.report('Error took place when run ' + command, {
|
||||
level: ReportType.Error
|
||||
});
|
||||
MainOutput.report('Reason: ' + stderr, {
|
||||
level: ReportType.Error
|
||||
});
|
||||
} else {
|
||||
MainOutput.report(stdout, {
|
||||
level: ReportType.Info
|
||||
});
|
||||
const vvpOutFile = hdlPath.join(simConfig.simulationHome, 'out.vvp');
|
||||
MainOutput.report("Create vvp to " + vvpOutFile, {
|
||||
level: ReportType.Run
|
||||
});
|
||||
|
||||
const outVvpPath = hdlPath.join(simConfig.simulationHome, 'out.vvp');
|
||||
const vvpPath = simConfig.vvpPath;
|
||||
|
||||
// run vvp to interrupt script
|
||||
const vvpCommand = `${vvpPath} ${outVvpPath}`;
|
||||
MainOutput.report(vvpCommand, {
|
||||
level: ReportType.Run
|
||||
});
|
||||
|
||||
child_process.exec(vvpCommand, { cwd }, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
MainOutput.report('Error took place when run ' + vvpCommand, {
|
||||
level: ReportType.Error
|
||||
});
|
||||
MainOutput.report('Reason: ' + stderr, {
|
||||
level: ReportType.Error
|
||||
});
|
||||
} else {
|
||||
MainOutput.report(stdout, {
|
||||
level: ReportType.Info
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
this.runIverilog(simConfig, command, cwd, hdlModule);
|
||||
}
|
||||
|
||||
private reportCommandError(command: string, stderr: string) {
|
||||
MainOutput.report(t('error.simulation.error-happen-run-command') + command, {
|
||||
level: ReportType.Error
|
||||
});
|
||||
MainOutput.report(t('error.simulation.reason', stderr), {
|
||||
level: ReportType.Error
|
||||
});
|
||||
}
|
||||
|
||||
private exec(command: string, cwd: AbsPath) {
|
||||
/**
|
||||
* @description 运行 iverilog xxx 的命令
|
||||
* @param simConfig
|
||||
* @param command
|
||||
* @param cwd
|
||||
* @param hdlModule
|
||||
*/
|
||||
private runIverilog(simConfig: SimulateConfig, command: string, cwd: string, hdlModule: HdlModule) {
|
||||
child_process.exec(command, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
this.reportCommandError(command, stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
// 准备执行 vvp
|
||||
MainOutput.report(stdout);
|
||||
const generateVvpName = hdlModule.name + '.vvp';
|
||||
|
||||
const outVvpPath = hdlPath.join(simConfig.simulationHome, generateVvpName);
|
||||
MainOutput.report(t('info.simulation.create-vvp', outVvpPath), {
|
||||
level: ReportType.Run
|
||||
});
|
||||
|
||||
const vvpPath = simConfig.vvpPath;
|
||||
|
||||
// 运行 vvp 文件,执行目录在生成的 vcd 的同级目录
|
||||
// 对于 vvp 执行的 cwd,为了方便用户可以调用 $readmemb $fopen $dumpfile
|
||||
// 这些系统调用进行 IO,所以选择 {workspace} 作为执行 vvp 的 cwd
|
||||
const vvpCwd = opeParam.openMode === 'file' ? cwd: opeParam.workspacePath;
|
||||
|
||||
const vvpCommand = `${vvpPath} ${outVvpPath}`;
|
||||
MainOutput.report(vvpCommand, { level: ReportType.Run });
|
||||
|
||||
this.runVvp(vvpCommand, vvpCwd);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 陨星 vvp xxx 的命令
|
||||
* @param command
|
||||
* @param cwd
|
||||
*/
|
||||
private runVvp(command: string, cwd: string) {
|
||||
child_process.exec(command, { cwd }, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
this.reportCommandError(command, stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
// 对于 vvp 的输出结果,特殊处理
|
||||
this.handleVvpStdOutput(stdout, command, cwd);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 处理 vvp xxx.vvp 执行后输出的标准输出
|
||||
* vvp 的标准输出似乎总是一行一个的
|
||||
* @param stdoutMessage vvp 执行后的标准输出窗口
|
||||
* @param command 用于重新执行
|
||||
* @param cwd 用于重新执行
|
||||
*/
|
||||
private handleVvpStdOutput(stdoutMessage: string, command: string, cwd: string) {
|
||||
for (const line of stdoutMessage.split('\n').map(line => line.trim())) {
|
||||
if (line.startsWith('WARNING:')) {
|
||||
// 运行时警告
|
||||
MainOutput.report(line.slice(8).trim(), { level: ReportType.Warn });
|
||||
|
||||
} else if (line.startsWith('ERROR:')) {
|
||||
// 运行时错误,比如用户 $readmemb 读取的文件并不存在
|
||||
MainOutput.report(line.slice(6).trim(), { level: ReportType.Error });
|
||||
|
||||
} else if (line.startsWith('VCD info:')) {
|
||||
// 导出 VCD 的信息,用于输出
|
||||
// 此处尝试提取 vcd 导出的信息,然后转换内部信息导出到屏幕上
|
||||
const match = line.match(/dumpfile (.+) opened for output/);
|
||||
if (match) {
|
||||
const vcdPath = match[1];
|
||||
const absVcdPath = hdlPath.resolve(cwd, vcdPath);
|
||||
MainOutput.report(t('info.simulate.vvp.vcd-generate', absVcdPath));
|
||||
} else {
|
||||
MainOutput.report(line.slice(9).trim());
|
||||
}
|
||||
|
||||
} else if (line.startsWith('VCD Error:')) {
|
||||
// 出现 VCD Error 可能是因为生成地点的目录不存在,创建目录,然后再运行
|
||||
const match = line.match(/Unable to open (.+) for output\./);
|
||||
if (match) {
|
||||
const vcdPath = match[1];
|
||||
const absVcdPath = hdlPath.resolve(cwd, vcdPath);
|
||||
const parentFolderPath = fspath.dirname(absVcdPath);
|
||||
hdlDir.mkdir(parentFolderPath);
|
||||
// 清除输出,准备第二次运行
|
||||
MainOutput.clear();
|
||||
this.runVvp(command, cwd);
|
||||
} else {
|
||||
// 没有匹配到,说明是其他错误,直接按照错误输出
|
||||
MainOutput.report(line.slice(10).trim(), { level: ReportType.Error });
|
||||
}
|
||||
} else {
|
||||
MainOutput.report(line, { level: ReportType.Info });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private exec(command: string, cwd: AbsPath, hdlModule: HdlModule) {
|
||||
const simConfig = this.simConfig;
|
||||
if (!simConfig) {
|
||||
MainOutput.report('this.simConfig is empty when exec');
|
||||
@ -350,10 +444,10 @@ class IcarusSimulate extends Simulate {
|
||||
const runInTerminal = vscode.workspace.getConfiguration().get('digital-ide.function.simulate.runInTerminal');
|
||||
|
||||
if (runInTerminal) {
|
||||
this.execInTerminal(command, cwd);
|
||||
this.execInTerminal(command, cwd, hdlModule);
|
||||
} else {
|
||||
MainOutput.show();
|
||||
this.execInOutput(command, cwd);
|
||||
this.execInOutput(command, cwd, hdlModule);
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,11 +469,12 @@ class IcarusSimulate extends Simulate {
|
||||
// MainOutput.report(warningMsg, ReportType.Warn, true);
|
||||
// return;
|
||||
// }
|
||||
|
||||
const dependences = this.getAllOtherDependences(path, name);
|
||||
const simulationCommand = this.getCommand(name, path, dependences);
|
||||
if (simulationCommand) {
|
||||
const cwd = hdlPath.resolve(path, '..');
|
||||
this.exec(simulationCommand, cwd);
|
||||
this.exec(simulationCommand, cwd, hdlModule);
|
||||
} else {
|
||||
const errorMsg = 'Fail to generate command';
|
||||
MainOutput.report(errorMsg, {
|
||||
|
@ -133,7 +133,7 @@ async function askUserToSaveFilelist(filelist: string[]) {
|
||||
if (uri === undefined) {
|
||||
return;
|
||||
}
|
||||
const filePath = uri.path;
|
||||
const filePath = uri.fsPath;
|
||||
const fileContent = filelist.join('\n');
|
||||
|
||||
try {
|
||||
|
@ -67,9 +67,6 @@ export function isSystemVerilogFile(path: AbsPath): boolean {
|
||||
}
|
||||
|
||||
export function isHDLFile(path: AbsPath): boolean {
|
||||
if (!isFile(path)) {
|
||||
return false;
|
||||
}
|
||||
const ext = hdlPath.extname(path, false);
|
||||
return hdlExts.includes(ext);
|
||||
}
|
||||
|
@ -103,6 +103,7 @@ function toEscapePath(path: AbsPath): AbsPath {
|
||||
}
|
||||
|
||||
function toPureRelativePath(path: RelPath): RelPath {
|
||||
|
||||
if (path.startsWith('./') || path.startsWith('.\\')) {
|
||||
return path.slice(2);
|
||||
}
|
||||
|
@ -169,6 +169,10 @@ class HdlParam {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (this.isTopModule(path, name)) {
|
||||
console.log(module);
|
||||
}
|
||||
|
||||
const dependencies : common.HdlDependence = {
|
||||
current: [],
|
||||
include: [],
|
||||
@ -497,15 +501,93 @@ class HdlParam {
|
||||
const hdlParam = new HdlParam();
|
||||
|
||||
class HdlInstance {
|
||||
name: string; // name of the instance
|
||||
type: string; // type
|
||||
/**
|
||||
* @description 例化的名字
|
||||
*
|
||||
* 对于下面的例子,唯一例化 的 name 就是 `u_tool`
|
||||
* @example
|
||||
* module hello()
|
||||
* tool u_tool();
|
||||
* endmodule
|
||||
*
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* @description 例化的模块名
|
||||
*
|
||||
* 对于下面的例子,唯一例化 的 type 就是 `tool`
|
||||
* @example
|
||||
* module hello()
|
||||
* tool u_tool();
|
||||
* endmodule
|
||||
*
|
||||
*/
|
||||
type: string;
|
||||
|
||||
/**
|
||||
* @description 例化的 range
|
||||
*/
|
||||
range: common.Range; // range of instance
|
||||
instModPath: AbsPath | undefined; // path of the definition
|
||||
instModPathStatus: common.InstModPathStatus; // status of the instance (current, include, others)
|
||||
instparams: common.InstRange; // range of params
|
||||
instports: common.InstRange; // range of ports
|
||||
parentMod: HdlModule; // 例化模块例化地点的外层 module
|
||||
module: HdlModule | undefined; // 例化模块的定义模块
|
||||
|
||||
/**
|
||||
* @description 例化的模块的定义路径
|
||||
*
|
||||
* 对于下面的例子,唯一例化 的 instModPath 就是 `tool` 这个模块 `module tool` 申明所在的文件的路径
|
||||
* @example
|
||||
* module hello()
|
||||
* tool u_tool();
|
||||
* endmodule
|
||||
*
|
||||
*/
|
||||
instModPath: AbsPath | undefined;
|
||||
|
||||
/**
|
||||
* @description 用于描述当前例化是如何被引入的,以下是三类枚举
|
||||
* - current: 例化对应的模块就在当前文件中
|
||||
* - include: 通过 `include
|
||||
* - others: 其他
|
||||
*/
|
||||
instModPathStatus: common.InstModPathStatus;
|
||||
|
||||
/**
|
||||
* @description 例化 params 部分的 range.
|
||||
* 如果是 vhdl,则是 generic map 部分的 range
|
||||
*/
|
||||
instparams: common.InstRange;
|
||||
|
||||
/**
|
||||
* @description 例化 ports 部分的 range.
|
||||
* 如果是 vhdl,则是 port map 部分的 range
|
||||
*/
|
||||
instports: common.InstRange;
|
||||
|
||||
/**
|
||||
* @description 例化模块例化地点的外层 module
|
||||
*
|
||||
* 对于下面的例子, 例化 `u_tool` 的 parentMod 就是 `hello`
|
||||
* @example
|
||||
* module hello()
|
||||
* tool u_tool();
|
||||
* endmodule
|
||||
*
|
||||
*/
|
||||
parentMod: HdlModule;
|
||||
|
||||
/**
|
||||
* @description 例化模块的定义模块
|
||||
*
|
||||
* 对于下面的例子, 例化 `u_tool` 的 `module` 就是 tool
|
||||
* @example
|
||||
* module hello();
|
||||
* tool u_tool();
|
||||
* endmodule
|
||||
*
|
||||
* module tool();
|
||||
* ...
|
||||
* endmodule
|
||||
*/
|
||||
module: HdlModule | undefined;
|
||||
|
||||
constructor(name: string,
|
||||
type: string,
|
||||
@ -611,7 +693,34 @@ class HdlInstance {
|
||||
this.instports = newInstance.instports;
|
||||
|
||||
this.instModPath = this.module?.path || '';
|
||||
this.instModPathStatus = this.parentMod.solveInstModPathStatus();
|
||||
this.updateInstModPathStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 用于解决例化的路径引入状态,对于 A 模块,它的两个例化 u_A1 和 u_A2
|
||||
* 使用 u_A1 和 u_A2 的模块需要知道 u_A1 是如何被引入的,此时需要调用 u_A1.updateInstModPathStatus() 来更新
|
||||
* u_A1 的 instModPathStatus
|
||||
*/
|
||||
public updateInstModPathStatus() {
|
||||
const module = this.module;
|
||||
if (module) {
|
||||
const userModule = this.parentMod;
|
||||
if (userModule.path === module.path) {
|
||||
this.instModPathStatus = common.InstModPathStatus.Current;
|
||||
} else {
|
||||
const userIncludePaths = userModule.file.macro.includes.map(
|
||||
include => hdlPath.rel2abs(userModule.path, include.path)
|
||||
);
|
||||
|
||||
if (userIncludePaths.includes(module.path)) {
|
||||
this.instModPathStatus = common.InstModPathStatus.Include;
|
||||
} else {
|
||||
this.instModPathStatus = common.InstModPathStatus.Others;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.instModPathStatus = common.InstModPathStatus.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
public get getDoFastFileType(): DoFastFileType | undefined {
|
||||
@ -882,28 +991,6 @@ class HdlModule {
|
||||
}
|
||||
}
|
||||
|
||||
public solveInstModPathStatus(): common.InstModPathStatus {
|
||||
// TODO: 修改这套系统,因为现在只是拿第一个例化来判断的,这是不合理的
|
||||
// 应该把 common.InstModPathStatus 修改成一个可以通过析取来表示的变量
|
||||
const inst = hdlParam.getUnhandleInstancesByModuleName(this.name)[0];
|
||||
if (!inst) {
|
||||
return common.InstModPathStatus.Unknown;
|
||||
}
|
||||
const userModule = inst.parentMod;
|
||||
if (userModule.path === this.path) {
|
||||
return common.InstModPathStatus.Current;
|
||||
} else {
|
||||
const userIncludePaths = userModule.file.macro.includes.map(
|
||||
include => hdlPath.rel2abs(userModule.path, include.path));
|
||||
|
||||
if (userIncludePaths.includes(this.path)) {
|
||||
return common.InstModPathStatus.Include;
|
||||
} else {
|
||||
return common.InstModPathStatus.Others;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 从全局寻找这个 module 的例化,并尝试修改它的状态
|
||||
*/
|
||||
@ -918,7 +1005,7 @@ class HdlModule {
|
||||
|
||||
// 解决
|
||||
instance.instModPath = this.path;
|
||||
instance.instModPathStatus = this.solveInstModPathStatus();
|
||||
instance.updateInstModPathStatus();
|
||||
|
||||
// 找寻这个 instance 对应的真正的 module(也有可能是原语)
|
||||
// 并将这个 instance 加入这个 module 的计数器中
|
||||
|
@ -1,8 +1,10 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { AbsPath, opeParam } from '../global';
|
||||
import { hdlPath } from '../hdlFs';
|
||||
import { hdlFile, hdlPath } from '../hdlFs';
|
||||
import * as fs from 'fs';
|
||||
import * as fspath from 'path';
|
||||
import { minimatch } from 'minimatch';
|
||||
import { toPureRelativePath } from '../hdlFs/path';
|
||||
|
||||
|
||||
class HdlIgnore {
|
||||
@ -19,9 +21,8 @@ class HdlIgnore {
|
||||
const workspace = opeParam.workspacePath;
|
||||
// 转换成相对于 ws 的相对路径,形如 ./src/test.py
|
||||
let relativePath = hdlPath.toPureRelativePath(hdlPath.relative(workspace, path));
|
||||
console.log('current path:', relativePath);
|
||||
|
||||
for (const pattern of this.patterns.map(p => hdlPath.toPureRelativePath(p))) {
|
||||
for (const pattern of this.patterns) {
|
||||
const matched = minimatch(relativePath, pattern);
|
||||
if (matched) {
|
||||
return true;
|
||||
@ -55,11 +56,26 @@ class HdlIgnore {
|
||||
}
|
||||
}
|
||||
this.patterns = [...validGlobStrings];
|
||||
this.makeClearPattern();
|
||||
} else {
|
||||
// .dideignore 不存在直接赋值为空
|
||||
this.patterns = [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 构建可直接使用的 patterns
|
||||
* 该操作是幂等的
|
||||
*/
|
||||
private makeClearPattern() {
|
||||
for (let i = 0; i < this.patterns.length; ++ i) {
|
||||
let pattern = this.patterns[i];
|
||||
if (fspath.isAbsolute(pattern)) {
|
||||
pattern = hdlPath.relative(opeParam.workspacePath, pattern);
|
||||
}
|
||||
this.patterns[i] = toPureRelativePath(pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const hdlIgnore = new HdlIgnore();
|
||||
|
@ -152,7 +152,7 @@ export class HdlAction extends BaseAction {
|
||||
* @param path
|
||||
*/
|
||||
private isvalid(path: AbsPath): boolean {
|
||||
const prjInfo = opeParam.prjInfo;
|
||||
const prjInfo = opeParam.prjInfo;
|
||||
if (path.startsWith(prjInfo.hardwareSrcPath) || path.startsWith(prjInfo.hardwareSimPath)) {
|
||||
if (!hdlIgnore.isignore(path) && hdlFile.isHDLFile(path)) {
|
||||
return true;
|
||||
|
@ -44,7 +44,6 @@ class HdlMonitor{
|
||||
*/
|
||||
public getHdlMonitor() {
|
||||
const prjInfo = opeParam.prjInfo;
|
||||
|
||||
const monitorPathSet = new PathSet();
|
||||
|
||||
// 在输出中展示当前的监视路径
|
||||
@ -57,8 +56,14 @@ class HdlMonitor{
|
||||
level: ReportType.Launch
|
||||
});
|
||||
|
||||
// chokidar 4.0.0 开始不支持 glob,需要在每一个入口自己判断
|
||||
return this.makeMonitor([opeParam.workspacePath, prjInfo.libCommonPath]);
|
||||
MainOutput.report(t('info.monitor.current-mode', opeParam.openMode));
|
||||
|
||||
if (opeParam.openMode === 'file') {
|
||||
return this.makeMonitor([prjInfo.libCommonPath]);
|
||||
} else {
|
||||
// chokidar 4.0.0 开始不支持 glob,需要在每一个入口自己判断
|
||||
return this.makeMonitor([opeParam.workspacePath, prjInfo.libCommonPath]);
|
||||
}
|
||||
}
|
||||
|
||||
public getIgnoreMonitor() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user