feat:接入iverilog工具
- 将iverilog可以随着插件的下载而下载 - 用户输入自然语言就可以控制生成对应的VCD文件
This commit is contained in:
@ -8,16 +8,28 @@ import {
|
||||
renameFile,
|
||||
replaceFile,
|
||||
} from "./createFiles";
|
||||
import {
|
||||
generateVCD,
|
||||
checkVerilogProject,
|
||||
checkIverilogAvailable,
|
||||
} from "./iverilogRunner";
|
||||
|
||||
/**
|
||||
* 处理用户消息
|
||||
*/
|
||||
export async function handleUserMessage(
|
||||
panel: vscode.WebviewPanel,
|
||||
text: string
|
||||
text: string,
|
||||
extensionPath?: string
|
||||
) {
|
||||
console.log("收到用户消息:", text);
|
||||
|
||||
// 检查是否是 VCD 生成命令
|
||||
if (isVCDGenerationCommand(text)) {
|
||||
await handleVCDGeneration(panel, extensionPath || "");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否是文件操作命令
|
||||
const fileOperation = parseFileOperation(text);
|
||||
|
||||
@ -466,3 +478,161 @@ export function insertCodeToEditor(code: string) {
|
||||
vscode.window.showWarningMessage("请先打开一个编辑器");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否是 VCD 生成命令
|
||||
*/
|
||||
function isVCDGenerationCommand(text: string): boolean {
|
||||
const lowerText = text.toLowerCase().trim();
|
||||
|
||||
// 匹配各种 VCD 生成命令
|
||||
const vcdPatterns = [
|
||||
/生成\s*vcd/,
|
||||
/创建\s*vcd/,
|
||||
/运行\s*仿真/,
|
||||
/执行\s*仿真/,
|
||||
/iverilog/,
|
||||
/生成\s*波形/,
|
||||
/仿真\s*生成/,
|
||||
];
|
||||
|
||||
return vcdPatterns.some((pattern) => pattern.test(lowerText));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 VCD 生成请求
|
||||
*/
|
||||
async function handleVCDGeneration(
|
||||
panel: vscode.WebviewPanel,
|
||||
extensionPath: string
|
||||
) {
|
||||
try {
|
||||
// 获取当前工作区路径
|
||||
const workspaceFolders = vscode.workspace.workspaceFolders;
|
||||
if (!workspaceFolders || workspaceFolders.length === 0) {
|
||||
panel.webview.postMessage({
|
||||
command: "receiveMessage",
|
||||
text: "❌ 请先打开一个工作区文件夹",
|
||||
});
|
||||
vscode.window.showErrorMessage("请先打开一个工作区文件夹");
|
||||
return;
|
||||
}
|
||||
|
||||
const projectPath = workspaceFolders[0].uri.fsPath;
|
||||
|
||||
// 发送开始消息
|
||||
panel.webview.postMessage({
|
||||
command: "receiveMessage",
|
||||
text: "🔍 正在检查项目文件...",
|
||||
});
|
||||
|
||||
// 1. 检查 iverilog 是否可用
|
||||
const iverilogCheck = await checkIverilogAvailable(extensionPath);
|
||||
if (!iverilogCheck.available) {
|
||||
panel.webview.postMessage({
|
||||
command: "receiveMessage",
|
||||
text: `❌ ${iverilogCheck.message}\n\n请参考插件文档安装 iverilog 工具。`,
|
||||
});
|
||||
vscode.window.showErrorMessage(iverilogCheck.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 检查项目文件完整性
|
||||
const projectCheck = await checkVerilogProject(projectPath);
|
||||
|
||||
if (!projectCheck.isComplete) {
|
||||
let errorMsg = "❌ 项目文件不完整:\n\n";
|
||||
|
||||
if (projectCheck.allVerilogFiles.length === 0) {
|
||||
errorMsg += "• 未找到任何 Verilog 文件 (.v 或 .sv)\n";
|
||||
} else {
|
||||
errorMsg += `• 找到 ${projectCheck.allVerilogFiles.length} 个 Verilog 文件\n`;
|
||||
|
||||
if (!projectCheck.hasTopModule) {
|
||||
errorMsg += "• ❌ 缺少顶层模块文件\n";
|
||||
} else {
|
||||
errorMsg += `• ✅ 顶层模块: ${projectCheck.topModuleFile}\n`;
|
||||
}
|
||||
|
||||
if (!projectCheck.hasTestbench) {
|
||||
errorMsg += "• ❌ 缺少 testbench 文件\n";
|
||||
errorMsg += "\n提示: testbench 文件应包含 $dumpfile 和 $dumpvars 语句来生成 VCD 文件。\n";
|
||||
} else {
|
||||
errorMsg += `• ✅ Testbench: ${projectCheck.testbenchFile}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
if (projectCheck.errors.length > 0) {
|
||||
errorMsg += "\n错误信息:\n" + projectCheck.errors.join("\n");
|
||||
}
|
||||
|
||||
panel.webview.postMessage({
|
||||
command: "receiveMessage",
|
||||
text: errorMsg,
|
||||
});
|
||||
vscode.window.showWarningMessage("项目文件不完整,无法生成 VCD");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 显示项目检查结果
|
||||
panel.webview.postMessage({
|
||||
command: "receiveMessage",
|
||||
text: `✅ 项目检查通过!\n\n找到 ${projectCheck.allVerilogFiles.length} 个 Verilog 文件\n• 顶层模块: ${projectCheck.topModuleFile}\n• Testbench: ${projectCheck.testbenchFile}\n\n🚀 开始编译和仿真...`,
|
||||
});
|
||||
|
||||
// 4. 生成 VCD 文件
|
||||
const result = await generateVCD(projectPath, extensionPath);
|
||||
|
||||
if (result.success) {
|
||||
let successMsg = `✅ ${result.message}`;
|
||||
|
||||
if (result.stdout) {
|
||||
successMsg += `\n\n仿真输出:\n${result.stdout}`;
|
||||
}
|
||||
|
||||
panel.webview.postMessage({
|
||||
command: "receiveMessage",
|
||||
text: successMsg,
|
||||
});
|
||||
|
||||
vscode.window.showInformationMessage(
|
||||
`VCD 文件生成成功: ${result.vcdFilePath}`,
|
||||
"打开文件"
|
||||
).then((selection) => {
|
||||
if (selection === "打开文件" && result.vcdFilePath) {
|
||||
vscode.workspace.openTextDocument(result.vcdFilePath).then((doc) => {
|
||||
vscode.window.showTextDocument(doc);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let errorMsg = `❌ ${result.message}`;
|
||||
|
||||
if (result.stderr) {
|
||||
errorMsg += `\n\n错误输出:\n${result.stderr}`;
|
||||
}
|
||||
|
||||
if (result.stdout) {
|
||||
errorMsg += `\n\n标准输出:\n${result.stdout}`;
|
||||
}
|
||||
|
||||
panel.webview.postMessage({
|
||||
command: "receiveMessage",
|
||||
text: errorMsg,
|
||||
});
|
||||
|
||||
vscode.window.showErrorMessage("VCD 文件生成失败");
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = `❌ 生成 VCD 文件时出错: ${
|
||||
error instanceof Error ? error.message : "未知错误"
|
||||
}`;
|
||||
|
||||
panel.webview.postMessage({
|
||||
command: "receiveMessage",
|
||||
text: errorMsg,
|
||||
});
|
||||
|
||||
vscode.window.showErrorMessage(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user