# Vivado 联动前后端对接文档 ## 1. 概述 本文档描述后端 AI 服务如何调用前端的 Vivado 工具,以及前端如何响应和返回结果。 ### 1.1 调用流程 ``` 后端 AI 服务 ↓ (1) 发送工具调用请求 前端 Extension (MessageHandler) ↓ (2) 解析请求,调用 VivadoRunner VivadoRunner ↓ (3) 执行 Vivado,实时推送进度 前端 Webview ↓ (4) 显示进度和结果 前端 Extension ↓ (5) 返回执行结果给后端 后端 AI 服务 ``` ## 2. 工具定义(后端) ### 2.1 工具注册 后端需要在工具列表中注册 `runVivado` 工具: ```json { "name": "runVivado", "description": "调用本地 Vivado 工具执行 FPGA 综合、实现或生成比特流。用于将 Verilog 代码部署到 FPGA 硬件。使用前必须先询问用户必要的参数(如芯片型号、执行模式)。", "inputSchema": { "type": "object", "properties": { "command": { "type": "string", "enum": ["synthesis", "implementation", "bitstream"], "description": "要执行的命令类型:synthesis(综合)、implementation(实现)、bitstream(生成比特流)" }, "topModule": { "type": "string", "description": "顶层模块名称" }, "files": { "type": "array", "items": { "type": "string" }, "description": "输入的 Verilog 文件路径列表" }, "constraints": { "type": "string", "description": "约束文件路径(.xdc 文件),可选" }, "part": { "type": "string", "description": "FPGA 芯片型号(如 xc7a35tcpg236-1),必须从用户处获取" }, "mode": { "type": "string", "enum": ["batch", "gui"], "description": "执行模式:batch(后台批处理)、gui(打开图形界面),必须询问用户" } }, "required": ["command", "topModule", "files", "part", "mode"] } } ``` ### 2.2 后端调用前的准备工作 **重要**:后端在调用 `runVivado` 工具前,必须先向用户询问必要参数: 1. **芯片型号(part)**:必须询问,例如 "xc7a35tcpg236-1" 2. **执行模式(mode)**:必须询问用户选择 - `batch`:后台批处理执行,自动完成 - `gui`:打开 Vivado 图形界面,用户手动操作 3. **顶层模块名**:可从文件名推断,但建议确认 4. **约束文件**:询问是否有时序约束文件(.xdc) **询问示例**: ``` AI: 我将使用 Vivado 进行综合。请提供以下信息: 1. FPGA 芯片型号(例如:xc7a35tcpg236-1) 2. 执行模式: - 批处理模式:后台自动执行,完成后返回结果 - 图形界面:打开 Vivado GUI,您可以手动操作 3. 是否有约束文件(.xdc)? 用户: xc7a35tcpg236-1,批处理模式,没有约束文件 AI: 好的,开始后台综合... [调用 runVivado 工具] ``` ### 2.3 调用示例 #### 示例 1:综合单个文件(批处理模式) ```json { "tool": "runVivado", "parameters": { "command": "synthesis", "topModule": "counter", "files": ["counter.v"], "part": "xc7a35tcpg236-1", "mode": "batch" } } ``` #### 示例 2:综合带约束文件(图形界面模式) ```json { "tool": "runVivado", "parameters": { "command": "synthesis", "topModule": "uart_top", "files": ["uart_tx.v", "uart_rx.v", "uart_top.v"], "constraints": "constraints.xdc", "part": "xc7k325tffg900-2", "mode": "gui" } } ``` #### 示例 3:实现(批处理模式) ```json { "tool": "runVivado", "parameters": { "command": "implementation", "topModule": "counter", "part": "xc7a35tcpg236-1", "mode": "batch" } } ``` #### 示例 4:生成比特流(图形界面) ```json { "tool": "runVivado", "parameters": { "command": "bitstream", "topModule": "counter", "part": "xc7a35tcpg236-1", "mode": "gui" } } ``` ## 3. 前端接收和处理 ### 3.1 后端如何控制前端 **核心机制**:后端通过调用 `runVivado` 工具来控制前端执行 Vivado 命令。 **控制流程**: 1. 后端识别用户意图(如"打开 Vivado"、"开始仿真") 2. 后端向用户询问必要参数(芯片型号等) 3. 后端调用 `runVivado` 工具,传递参数 4. 前端接收工具调用,执行相应操作 5. 前端返回执行结果给后端 6. 后端将结果展示给用户 **示例场景**: ``` 用户输入:"打开 Vivado 进行综合" 后端处理: 1. 识别意图 → 需要调用 runVivado 工具 2. 检查参数 → 缺少芯片型号 3. 询问用户 → "请提供 FPGA 芯片型号" 4. 用户回复 → "xc7a35tcpg236-1" 5. 调用工具 → runVivado({ command: "synthesis", part: "xc7a35tcpg236-1", ... }) 6. 前端执行 → VivadoRunner 启动 Vivado 7. 返回结果 → { success: true, ... } 8. 展示结果 → "综合完成,耗时 45 秒" ``` ### 3.2 MessageHandler 处理逻辑 前端在 `messageHandler.ts` 中添加工具处理: ```typescript // src/utils/messageHandler.ts export async function handleToolExecution( panel: vscode.WebviewPanel, toolName: string, parameters: any ): Promise { if (toolName === 'runVivado') { return await handleVivadoTool(panel, parameters); } // 其他工具处理... } async function handleVivadoTool( panel: vscode.WebviewPanel, parameters: any ): Promise { const { command, topModule, files, constraints, part, mode } = parameters; // 验证必需参数 if (!part) { return { success: false, command, executionTime: 0, output: '', error: '缺少必需参数:芯片型号(part)。后端应该先询问用户。' }; } if (!mode) { return { success: false, command, executionTime: 0, output: '', error: '缺少必需参数:执行模式(mode)。后端应该询问用户选择 batch 或 gui。' }; } // 构建请求 const request: VivadoToolRequest = { command, parameters: { topModule, files, constraints, part, mode }, importOutput: { enabled: mode === 'batch', // 只有批处理模式才自动导入 targetDir: path.join( vscode.workspace.workspaceFolders![0].uri.fsPath, 'vivado_output' ) } }; // 向前端发送开始消息 panel.webview.postMessage({ type: 'vivado-start', command }); // 执行 Vivado const response = await runVivado(request, (progress) => { // 实时推送进度到前端 panel.webview.postMessage({ type: 'vivado-progress', progress }); }); // 向前端发送完成消息 panel.webview.postMessage({ type: 'vivado-complete', response }); // 返回结果给后端 return response; } ``` ## 4. 响应格式 ### 4.1 成功响应 ```json { "success": true, "command": "synthesis", "executionTime": 45230, "output": "Vivado 执行日志...", "importedFiles": [ "/path/to/vivado_output/counter_synth.dcp", "/path/to/vivado_output/counter_utilization_synth.rpt" ], "reports": { "resources": "LUT: 32/20800 (0.15%)\nFF: 8/41600 (0.02%)", "timing": "WNS: 5.234ns, TNS: 0.000ns" } } ``` ### 4.2 失败响应 ```json { "success": false, "command": "synthesis", "executionTime": 1250, "output": "部分执行日志...", "error": "ERROR: [Synth 8-439] module 'counter' not found" } ``` ## 5. 后端使用指南 ### 5.1 AI 对话流程(完整版) ``` 用户:帮我用 Vivado 综合一下 counter.v AI 分析: 1. 用户想要综合 Verilog 文件 2. 需要调用 runVivado 工具 3. 命令类型是 synthesis 4. 顶层模块名从文件名推断为 counter 5. 输入文件是 counter.v 6. ⚠️ 缺少必要参数:芯片型号 AI 回复用户: "好的,我将使用 Vivado 进行综合。请提供以下信息: 1. FPGA 芯片型号(例如:xc7a35tcpg236-1、xc7k325tffg900-2) 2. 是否有约束文件(.xdc)?" 用户:xc7a35tcpg236-1,没有约束文件 AI 调用工具: { "tool": "runVivado", "parameters": { "command": "synthesis", "topModule": "counter", "files": ["counter.v"], "part": "xc7a35tcpg236-1" } } 前端执行并返回结果 AI 回复用户: "Vivado 综合完成! - 执行时间:45.2 秒 - 芯片型号:xc7a35tcpg236-1 - 资源使用:LUT: 32/20800 (0.15%), FF: 8/41600 (0.02%) - 产出文件已导入到 vivado_output 目录" ``` ### 5.2 完整流程示例 ``` 用户:用 Vivado 跑完整个流程 AI:好的,我将依次执行综合、实现和生成比特流。请提供: 1. FPGA 芯片型号 2. 顶层模块名 3. 是否有约束文件 用户:xc7a35tcpg236-1,顶层模块是 counter,没有约束文件 AI:收到,开始执行... 步骤 1:综合 [调用] runVivado { command: "synthesis", topModule: "counter", files: ["counter.v"], part: "xc7a35tcpg236-1" } [结果] 综合成功,耗时 45s 步骤 2:实现 [调用] runVivado { command: "implementation", topModule: "counter", part: "xc7a35tcpg236-1" } [结果] 实现成功,耗时 120s,时序满足要求 步骤 3:生成比特流 [调用] runVivado { command: "bitstream", topModule: "counter", part: "xc7a35tcpg236-1" } [结果] 比特流生成成功,文件:counter.bit 完成!所有文件已导入到 vivado_output 目录。 ``` ## 6. 错误处理 ### 6.1 常见错误 #### 错误 1:Vivado 未配置 ```json { "success": false, "error": "Vivado 未配置,请在设置中配置 Vivado 路径" } ``` **AI 应该回复**: "Vivado 尚未配置,请先在插件设置中配置 Vivado 的安装路径。" #### 错误 2:文件不存在 ```json { "success": false, "error": "输入文件不存在: counter.v" } ``` **AI 应该回复**: "找不到文件 counter.v,请确认文件路径是否正确。" #### 错误 3:综合失败 ```json { "success": false, "error": "ERROR: [Synth 8-439] module 'counter' not found", "output": "详细日志..." } ``` **AI 应该回复**: "综合失败,错误信息:找不到模块 'counter'。请检查: 1. 模块名是否正确 2. 文件中是否定义了该模块 3. 是否有语法错误" ### 6.2 错误处理建议 后端收到 `success: false` 时: 1. 提取 `error` 字段中的错误信息 2. 分析错误类型(配置问题、文件问题、语法问题等) 3. 给用户提供具体的解决建议 4. 必要时可以查看 `output` 字段获取详细日志 ## 7. 进度推送(可选) 前端会实时推送进度信息到 Webview,后端无需处理,但可以了解进度格式: ```json { "type": "vivado-progress", "progress": { "stage": "synthesis", "percentage": 45, "message": "正在综合模块 counter..." } } ``` ## 8. 测试建议 ### 8.1 后端测试用例 ```javascript // 测试用例 1:基本综合 test('综合单个文件', async () => { const result = await callTool('runVivado', { command: 'synthesis', topModule: 'counter', files: ['counter.v'] }); expect(result.success).toBe(true); expect(result.importedFiles.length).toBeGreaterThan(0); }); // 测试用例 2:错误处理 test('文件不存在', async () => { const result = await callTool('runVivado', { command: 'synthesis', topModule: 'test', files: ['not_exist.v'] }); expect(result.success).toBe(false); expect(result.error).toContain('不存在'); }); ``` ## 9. 注意事项 ### 9.1 后端必须询问的参数 **关键要求**:后端在调用 `runVivado` 前,必须先向用户收集以下参数: | 参数 | 是否必须 | 询问方式 | 示例 | |------|---------|---------|------| | part(芯片型号) | ✅ 必须 | 直接询问 | "请提供 FPGA 芯片型号(如 xc7a35tcpg236-1)" | | mode(执行模式) | ✅ 必须 | 提供选项 | "选择执行模式:1.批处理 2.图形界面" | | topModule | ✅ 必须 | 可推断或询问 | 从文件名推断,或询问"顶层模块名是什么?" | | files | ✅ 必须(综合时) | 可推断或询问 | 从当前文件或工作区推断 | | constraints | ❌ 可选 | 询问 | "是否有约束文件(.xdc)?" | ### 9.2 常见用户输入场景 #### 场景 1:用户说"打开 Vivado" ``` 用户:打开 Vivado 后端分析:用户想使用 Vivado,但没有指定具体操作 后端回复: "好的,请问您想执行什么操作? 1. 综合(Synthesis)- 将 Verilog 转换为门级网表 2. 实现(Implementation)- 布局布线 3. 生成比特流(Bitstream)- 生成 .bit 文件 另外,请提供: - FPGA 芯片型号(例如:xc7a35tcpg236-1) - 执行模式:批处理(后台自动)或 图形界面(手动操作)" ``` #### 场景 2:用户说"开始仿真" ``` 用户:开始仿真 后端分析:用户可能混淆了仿真和综合 后端回复: "您是想: 1. 使用 iverilog 进行功能仿真(验证逻辑) 2. 使用 Vivado 进行综合(部署到 FPGA) 请选择您需要的操作。" ``` #### 场景 3:用户提供完整信息 ``` 用户:用 Vivado 综合 counter.v,芯片是 xc7a35tcpg236-1,批处理模式 后端分析:信息完整,可以直接调用 后端操作: [调用] runVivado({ command: "synthesis", topModule: "counter", files: ["counter.v"], part: "xc7a35tcpg236-1", mode: "batch" }) ``` #### 场景 4:用户选择图形界面 ``` 用户:打开 Vivado 图形界面做综合 后端分析:用户明确要求 GUI 模式 后端询问: "好的,请提供: 1. FPGA 芯片型号 2. 顶层模块名" 用户:xc7a35tcpg236-1, counter 后端操作: [调用] runVivado({ command: "synthesis", topModule: "counter", files: ["counter.v"], part: "xc7a35tcpg236-1", mode: "gui" }) 前端执行: - 生成 TCL 脚本和项目文件 - 执行: vivado counter_project.xpr (打开图形界面) - 返回: { success: true, message: "Vivado GUI 已启动" } 后端回复: "Vivado 图形界面已打开,您可以在界面中手动操作。" ``` ### 9.3 执行时间 - 综合:小型设计 30s-2min,大型设计 5-30min - 实现:通常是综合时间的 2-3 倍 - 生成比特流:通常 10-30s 后端应该设置合理的超时时间(建议 10 分钟)。 ### 9.4 依赖关系 - `implementation` 需要先执行 `synthesis` - `bitstream` 需要先执行 `implementation` 后端 AI 应该理解这个依赖关系,按顺序调用。 ### 9.5 文件路径 - 所有文件路径都是相对于工作区根目录 - 前端会自动解析为绝对路径 - 支持相对路径和绝对路径 ## 10. 参数传递详细说明 ### 10.1 必需参数 | 参数 | 类型 | 说明 | 获取方式 | |------|------|------|----------| | command | string | 命令类型 | 从用户意图推断 | | topModule | string | 顶层模块名 | 从文件名推断或询问用户 | | files | string[] | 源文件列表 | 从工作区查找或用户指定 | | part | string | 芯片型号 | **必须询问用户** | ### 10.2 可选参数 | 参数 | 类型 | 说明 | 默认值 | |------|------|------|--------| | constraints | string | 约束文件路径 | 无 | ### 10.3 参数验证规则 后端在调用前应验证: - `part` 格式正确(如 xc7a35tcpg236-1) - `files` 数组不为空 - `topModule` 不为空 - `command` 在枚举值内 ## 11. 快速集成清单 后端开发者需要做的事情: - [ ] 在工具列表中注册 `runVivado` 工具 - [ ] **实现参数询问逻辑(芯片型号等)** - [ ] 实现工具调用逻辑(发送请求到前端) - [ ] 处理返回结果(success/error) - [ ] 实现错误处理和用户提示 - [ ] 理解三个命令的依赖关系 - [ ] 设置合理的超时时间(建议 10 分钟) - [ ] 编写测试用例 前端开发者需要做的事情: - [ ] 实现 `handleVivadoTool` 函数 - [ ] 集成 VivadoRunner - [ ] 实现进度推送 - [ ] 实现结果展示 - [ ] 处理各种错误情况 - [ ] 验证传入的参数完整性