From aa80088abc421d61d3ba88e2a35208608f17d501 Mon Sep 17 00:00:00 2001 From: Roe-xin Date: Mon, 16 Mar 2026 14:05:34 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=AE=8C=E5=96=84=20Vivado=20=E8=81=94?= =?UTF-8?q?=E5=8A=A8=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加后端工具调用控制前端的详细说明 - 新增 mode 参数(batch/gui)支持批处理和图形界面模式 - 补充参数询问流程和验证规则 - 添加完整实现示例:生成比特流和布局布线 - 更新所有调用示例包含必需参数 --- docs/EDA联动功能需求文档.md | 34 +++- docs/Vivado联动前后端对接文档.md | 278 ++++++++++++++++++++++++++--- docs/Vivado联动功能技术设计文档.md | 65 ++++++- 3 files changed, 342 insertions(+), 35 deletions(-) diff --git a/docs/EDA联动功能需求文档.md b/docs/EDA联动功能需求文档.md index 50ed7c7..e7cfd69 100644 --- a/docs/EDA联动功能需求文档.md +++ b/docs/EDA联动功能需求文档.md @@ -217,34 +217,58 @@ write_checkpoint -force counter_synth.dcp ```json { "name": "runVivado", - "description": "调用 Vivado 执行综合、实现或生成比特流", + "description": "调用 Vivado 执行综合、实现或生成比特流。使用前必须先询问用户芯片型号等必要参数。", "parameters": { "command": "命令类型(synthesis/implementation/bitstream)", "topModule": "顶层模块名", "files": "输入文件列表", + "part": "FPGA 芯片型号(必须从用户获取)", "constraints": "约束文件路径(可选)" } } ``` -#### 3.6.2 调用示例 +#### 3.6.2 后端交互流程 + +**关键点**:后端必须先收集必要参数,再调用工具 + +1. **用户发起请求**:"打开 Vivado" 或 "用 Vivado 综合" +2. **后端识别意图**:需要调用 runVivado 工具 +3. **后端询问参数**: + - FPGA 芯片型号(必须) + - 约束文件(可选) + - 确认顶层模块名 +4. **用户提供参数** +5. **后端调用工具**:传递完整参数给前端 +6. **前端执行**:VivadoRunner 执行命令 +7. **返回结果**:后端接收结果并展示给用户 + +#### 3.6.3 调用示例(完整交互) ``` 用户:帮我用 Vivado 综合一下 counter.v -AI:好的,我将使用 Vivado 进行综合。 + +AI:好的,我将使用 Vivado 进行综合。请提供以下信息: + 1. FPGA 芯片型号(例如:xc7a35tcpg236-1) + 2. 是否有约束文件(.xdc)? + +用户:xc7a35tcpg236-1,没有约束文件 + +AI:收到,开始综合... [调用工具] runVivado 参数: - command: synthesis - topModule: counter - files: ["counter.v"] - - constraints: "constraints.xdc" + - part: "xc7a35tcpg236-1" [执行中...] Vivado 综合完成! + - 芯片型号:xc7a35tcpg236-1 - 执行时间:45 秒 - 资源使用:LUT: 32/20800 (0.15%), FF: 8/41600 (0.02%) - 产出文件:counter_synth.dcp, utilization_synth.rpt - - 已自动导入到:vivado_project/output/ + - 已自动导入到:vivado_output/ ``` ## 4. 用户场景 diff --git a/docs/Vivado联动前后端对接文档.md b/docs/Vivado联动前后端对接文档.md index c4f15f8..3281be4 100644 --- a/docs/Vivado联动前后端对接文档.md +++ b/docs/Vivado联动前后端对接文档.md @@ -29,7 +29,7 @@ VivadoRunner ```json { "name": "runVivado", - "description": "调用本地 Vivado 工具执行 FPGA 综合、实现或生成比特流。用于将 Verilog 代码部署到 FPGA 硬件。", + "description": "调用本地 Vivado 工具执行 FPGA 综合、实现或生成比特流。用于将 Verilog 代码部署到 FPGA 硬件。使用前必须先询问用户必要的参数(如芯片型号、执行模式)。", "inputSchema": { "type": "object", "properties": { @@ -53,17 +53,48 @@ VivadoRunner }, "part": { "type": "string", - "description": "FPGA 型号,可选,默认使用配置中的型号" + "description": "FPGA 芯片型号(如 xc7a35tcpg236-1),必须从用户处获取" + }, + "mode": { + "type": "string", + "enum": ["batch", "gui"], + "description": "执行模式:batch(后台批处理)、gui(打开图形界面),必须询问用户" } }, - "required": ["command", "topModule", "files"] + "required": ["command", "topModule", "files", "part", "mode"] } } ``` -### 2.2 调用示例 +### 2.2 后端调用前的准备工作 -#### 示例 1:综合单个文件 +**重要**:后端在调用 `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 { @@ -71,12 +102,14 @@ VivadoRunner "parameters": { "command": "synthesis", "topModule": "counter", - "files": ["counter.v"] + "files": ["counter.v"], + "part": "xc7a35tcpg236-1", + "mode": "batch" } } ``` -#### 示例 2:综合带约束文件 +#### 示例 2:综合带约束文件(图形界面模式) ```json { @@ -85,38 +118,71 @@ VivadoRunner "command": "synthesis", "topModule": "uart_top", "files": ["uart_tx.v", "uart_rx.v", "uart_top.v"], - "constraints": "constraints.xdc" + "constraints": "constraints.xdc", + "part": "xc7k325tffg900-2", + "mode": "gui" } } ``` -#### 示例 3:实现(需要先综合) +#### 示例 3:实现(批处理模式) ```json { "tool": "runVivado", "parameters": { "command": "implementation", - "topModule": "counter" + "topModule": "counter", + "part": "xc7a35tcpg236-1", + "mode": "batch" } } ``` -#### 示例 4:生成比特流(需要先实现) +#### 示例 4:生成比特流(图形界面) ```json { "tool": "runVivado", "parameters": { "command": "bitstream", - "topModule": "counter" + "topModule": "counter", + "part": "xc7a35tcpg236-1", + "mode": "gui" } } ``` ## 3. 前端接收和处理 -### 3.1 MessageHandler 处理逻辑 +### 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` 中添加工具处理: @@ -141,7 +207,28 @@ async function handleVivadoTool( parameters: any ): Promise { - const { command, topModule, files, constraints, part } = parameters; + 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 = { @@ -150,10 +237,11 @@ async function handleVivadoTool( topModule, files, constraints, - part + part, + mode }, importOutput: { - enabled: true, + enabled: mode === 'batch', // 只有批处理模式才自动导入 targetDir: path.join( vscode.workspace.workspaceFolders![0].uri.fsPath, 'vivado_output' @@ -222,7 +310,7 @@ async function handleVivadoTool( ## 5. 后端使用指南 -### 5.1 AI 对话流程 +### 5.1 AI 对话流程(完整版) ``` 用户:帮我用 Vivado 综合一下 counter.v @@ -233,6 +321,14 @@ AI 分析: 3. 命令类型是 synthesis 4. 顶层模块名从文件名推断为 counter 5. 输入文件是 counter.v +6. ⚠️ 缺少必要参数:芯片型号 + +AI 回复用户: +"好的,我将使用 Vivado 进行综合。请提供以下信息: +1. FPGA 芯片型号(例如:xc7a35tcpg236-1、xc7k325tffg900-2) +2. 是否有约束文件(.xdc)?" + +用户:xc7a35tcpg236-1,没有约束文件 AI 调用工具: { @@ -240,7 +336,8 @@ AI 调用工具: "parameters": { "command": "synthesis", "topModule": "counter", - "files": ["counter.v"] + "files": ["counter.v"], + "part": "xc7a35tcpg236-1" } } @@ -249,6 +346,7 @@ AI 调用工具: AI 回复用户: "Vivado 综合完成! - 执行时间:45.2 秒 +- 芯片型号:xc7a35tcpg236-1 - 资源使用:LUT: 32/20800 (0.15%), FF: 8/41600 (0.02%) - 产出文件已导入到 vivado_output 目录" ``` @@ -258,18 +356,25 @@ AI 回复用户: ``` 用户:用 Vivado 跑完整个流程 -AI:好的,我将依次执行综合、实现和生成比特流。 +AI:好的,我将依次执行综合、实现和生成比特流。请提供: +1. FPGA 芯片型号 +2. 顶层模块名 +3. 是否有约束文件 + +用户:xc7a35tcpg236-1,顶层模块是 counter,没有约束文件 + +AI:收到,开始执行... 步骤 1:综合 -[调用] runVivado { command: "synthesis", ... } +[调用] runVivado { command: "synthesis", topModule: "counter", files: ["counter.v"], part: "xc7a35tcpg236-1" } [结果] 综合成功,耗时 45s 步骤 2:实现 -[调用] runVivado { command: "implementation", ... } +[调用] runVivado { command: "implementation", topModule: "counter", part: "xc7a35tcpg236-1" } [结果] 实现成功,耗时 120s,时序满足要求 步骤 3:生成比特流 -[调用] runVivado { command: "bitstream", ... } +[调用] runVivado { command: "bitstream", topModule: "counter", part: "xc7a35tcpg236-1" } [结果] 比特流生成成功,文件:counter.bit 完成!所有文件已导入到 vivado_output 目录。 @@ -374,34 +479,152 @@ test('文件不存在', async () => { ## 9. 注意事项 -### 9.1 执行时间 +### 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.2 依赖关系 +### 9.4 依赖关系 - `implementation` 需要先执行 `synthesis` - `bitstream` 需要先执行 `implementation` 后端 AI 应该理解这个依赖关系,按顺序调用。 -### 9.3 文件路径 +### 9.5 文件路径 - 所有文件路径都是相对于工作区根目录 - 前端会自动解析为绝对路径 - 支持相对路径和绝对路径 -## 10. 快速集成清单 +## 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 分钟) - [ ] 编写测试用例 前端开发者需要做的事情: @@ -411,3 +634,4 @@ test('文件不存在', async () => { - [ ] 实现进度推送 - [ ] 实现结果展示 - [ ] 处理各种错误情况 +- [ ] 验证传入的参数完整性 diff --git a/docs/Vivado联动功能技术设计文档.md b/docs/Vivado联动功能技术设计文档.md index b91c4be..093ce99 100644 --- a/docs/Vivado联动功能技术设计文档.md +++ b/docs/Vivado联动功能技术设计文档.md @@ -548,8 +548,19 @@ import { runVivado } from './vivadoRunner'; export async function handleVivadoTool( panel: vscode.WebviewPanel, toolCall: any -): Promise { - const { command, topModule, files, constraints } = toolCall.parameters; +): Promise { + const { command, topModule, files, constraints, part } = toolCall.parameters; + + // 验证必需参数 + if (!part) { + return { + success: false, + command, + executionTime: 0, + output: '', + error: '缺少必需参数:芯片型号(part)' + }; + } // 构建请求 const request: VivadoToolRequest = { @@ -557,7 +568,8 @@ export async function handleVivadoTool( parameters: { topModule, files, - constraints + constraints, + part }, importOutput: { enabled: true, @@ -585,6 +597,53 @@ export async function handleVivadoTool( type: 'vivado-complete', response }); + + // 返回结果给后端 + return response; +} +``` + +### 3.6 参数验证和处理 + +```typescript +// src/utils/vivadoValidator.ts + +export interface ValidationResult { + valid: boolean; + error?: string; +} + +export function validateVivadoRequest(request: VivadoToolRequest): ValidationResult { + const { command, parameters } = request; + + // 验证命令类型 + if (!['synthesis', 'implementation', 'bitstream'].includes(command)) { + return { valid: false, error: `无效的命令类型: ${command}` }; + } + + // 验证必需参数 + if (!parameters?.topModule) { + return { valid: false, error: '缺少顶层模块名(topModule)' }; + } + + if (!parameters?.part) { + return { valid: false, error: '缺少芯片型号(part)' }; + } + + // 验证芯片型号格式 + const partPattern = /^xc[0-9a-z]+$/i; + if (!partPattern.test(parameters.part)) { + return { valid: false, error: `芯片型号格式不正确: ${parameters.part}` }; + } + + // 综合命令需要文件列表 + if (command === 'synthesis') { + if (!parameters?.files || parameters.files.length === 0) { + return { valid: false, error: '综合命令需要提供源文件列表' }; + } + } + + return { valid: true }; } ```