445 lines
10 KiB
Markdown
445 lines
10 KiB
Markdown
# 波形预览功能技术文档
|
||
|
||
## 功能概述
|
||
|
||
在对话界面中显示 VCD 波形文件的预览卡片,用户可以查看前几个信号的真实波形,并通过"展开查看"按钮打开完整的波形查看器。
|
||
|
||
## 功能流程
|
||
|
||
```
|
||
用户输入"生成VCD"命令
|
||
↓
|
||
系统执行 iverilog 编译和仿真
|
||
↓
|
||
生成 VCD 文件
|
||
↓
|
||
在对话界面显示波形预览卡片
|
||
├─ 显示真实的波形图(前3个信号)
|
||
├─ 显示信号名称和波形
|
||
└─ "展开查看"按钮
|
||
↓
|
||
点击"展开查看"按钮
|
||
↓
|
||
打开完整的 VCDViewerPanel 波形查看器
|
||
```
|
||
|
||
## 文件结构
|
||
|
||
### 1. `src/views/waveformPreviewContent.ts`
|
||
**功能:** 波形预览组件的独立模块
|
||
|
||
**导出函数:**
|
||
- `getWaveformPreviewContent()` - 返回波形预览组件的 CSS 样式
|
||
- `getWaveformPreviewScript()` - 返回波形预览组件的 JavaScript 代码
|
||
|
||
**主要功能:**
|
||
- 创建波形预览卡片的 HTML 结构
|
||
- 从 VCD 文件中提取真实信号数据
|
||
- 使用 SVG 绘制波形图
|
||
- 单比特信号:绘制数字波形(高/低电平)
|
||
- 多比特信号:绘制总线波形(梯形)
|
||
- 处理"展开查看"按钮点击事件
|
||
|
||
**关键函数:**
|
||
```javascript
|
||
createWaveformPreview(vcdFilePath, fileName)
|
||
- 创建波形预览卡片的 DOM 结构
|
||
- 包含头部(标题 + 展开按钮)和内容区域
|
||
|
||
loadMiniWaveform(containerId, vcdFilePath, loadingDiv)
|
||
- 请求后端获取 VCD 文件信息
|
||
|
||
renderWaveformInfo(containerId, vcdInfo)
|
||
- 接收 VCD 信息并渲染波形
|
||
|
||
drawRealWaveform(signals)
|
||
- 根据真实信号数据绘制 SVG 波形图
|
||
- 支持单比特和多比特信号
|
||
- 使用不同颜色区分信号
|
||
|
||
openFullWaveform(vcdFilePath)
|
||
- 发送消息打开完整波形查看器
|
||
|
||
addWaveformPreviewToMessage(messageDiv, vcdFilePath, fileName)
|
||
- 将波形预览组件添加到消息中
|
||
```
|
||
|
||
---
|
||
|
||
### 2. `src/views/webviewContent.ts`
|
||
**功能:** 主 WebView 页面,集成波形预览组件
|
||
|
||
**修改内容:**
|
||
- 导入波形预览组件的样式和脚本
|
||
- 在 `<style>` 标签中插入 `getWaveformPreviewContent()`
|
||
- 在 `<script>` 标签中插入 `getWaveformPreviewScript()`
|
||
- 添加 `vcdGenerated` 消息处理逻辑
|
||
- 添加 `vcdInfo` 消息处理逻辑
|
||
|
||
**消息处理:**
|
||
```javascript
|
||
case 'vcdGenerated':
|
||
// VCD 文件生成成功,显示带波形预览的消息
|
||
- 创建消息 div
|
||
- 添加成功消息文本
|
||
- 调用 addWaveformPreviewToMessage() 添加波形预览卡片
|
||
|
||
case 'vcdInfo':
|
||
// 接收到 VCD 文件信息,渲染波形预览
|
||
- 调用 renderWaveformInfo() 渲染波形
|
||
```
|
||
|
||
---
|
||
|
||
### 3. `src/utils/messageHandler.ts`
|
||
**功能:** 处理用户消息和 VCD 生成请求
|
||
|
||
**修改内容:**
|
||
- 导入 `path` 模块
|
||
- 修改 VCD 生成成功后的消息发送逻辑
|
||
|
||
**关键代码:**
|
||
```typescript
|
||
if (result.success) {
|
||
if (result.vcdFilePath) {
|
||
const fileName = path.basename(result.vcdFilePath);
|
||
panel.webview.postMessage({
|
||
command: "vcdGenerated", // 发送 vcdGenerated 消息
|
||
text: successMsg,
|
||
vcdFilePath: result.vcdFilePath,
|
||
fileName: fileName,
|
||
});
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 4. `src/panels/ICHelperPanel.ts`
|
||
**功能:** IC 助手面板,处理 WebView 消息
|
||
|
||
**修改内容:**
|
||
- 导入 `VCDViewerPanel`
|
||
- 添加 `openWaveformViewer` 命令处理
|
||
- 添加 `getVCDInfo` 命令处理
|
||
- 新增 `getVCDFileInfo()` 函数
|
||
- 新增 `parseVCDSignals()` 函数
|
||
|
||
**新增函数:**
|
||
|
||
#### `getVCDFileInfo(panel, vcdFilePath, containerId)`
|
||
**功能:** 获取 VCD 文件信息并解析信号数据
|
||
|
||
**处理流程:**
|
||
1. 检查文件是否存在
|
||
2. 获取文件大小
|
||
3. 读取 VCD 文件内容
|
||
4. 解析信号数量
|
||
5. 解析时间范围
|
||
6. 调用 `parseVCDSignals()` 解析前 3 个信号的数据
|
||
7. 发送 `vcdInfo` 消息回前端
|
||
|
||
**返回数据结构:**
|
||
```typescript
|
||
{
|
||
command: "vcdInfo",
|
||
containerId: string,
|
||
vcdInfo: {
|
||
signalCount: string,
|
||
timeRange: string,
|
||
fileSize: string,
|
||
signals: Array<{
|
||
name: string,
|
||
identifier: string,
|
||
width: number,
|
||
values: Array<{ time: number, value: string }>
|
||
}>
|
||
}
|
||
}
|
||
```
|
||
|
||
#### `parseVCDSignals(content, maxSignals)`
|
||
**功能:** 解析 VCD 文件中的信号数据
|
||
|
||
**处理流程:**
|
||
1. 使用正则表达式解析信号定义部分(`$var ... $end`)
|
||
2. 提取信号名称、标识符、位宽
|
||
3. 找到数据变化部分(`$dumpvars` 之后)
|
||
4. 解析每个信号的值变化
|
||
- 单比特信号:格式 `0!` 或 `1!`
|
||
- 多比特信号:格式 `b1010 !`
|
||
5. 限制最多 50 个采样点(避免数据过多)
|
||
6. 返回信号数据数组
|
||
|
||
**VCD 文件格式示例:**
|
||
```vcd
|
||
$var wire 1 ! clk $end
|
||
$var wire 8 " data $end
|
||
$dumpvars
|
||
0!
|
||
b00000000 "
|
||
#10
|
||
1!
|
||
#20
|
||
0!
|
||
b00000001 "
|
||
```
|
||
|
||
**消息处理:**
|
||
```typescript
|
||
case "openWaveformViewer":
|
||
// 打开完整波形查看器
|
||
VCDViewerPanel.createOrShow(context.extensionUri, message.vcdFilePath);
|
||
|
||
case "getVCDInfo":
|
||
// 获取 VCD 文件信息
|
||
getVCDFileInfo(panel, message.vcdFilePath, message.containerId);
|
||
```
|
||
|
||
---
|
||
|
||
### 5. `src/panels/VCDViewerPanel.ts`
|
||
**功能:** 完整的 VCD 波形查看器面板(已存在)
|
||
|
||
**作用:** 当用户点击"展开查看"按钮时,打开此面板显示完整的波形
|
||
|
||
---
|
||
|
||
## 数据流
|
||
|
||
### 1. VCD 生成流程
|
||
```
|
||
用户输入 → messageHandler.handleUserMessage()
|
||
↓
|
||
检测到 VCD 生成命令
|
||
↓
|
||
messageHandler.handleVCDGeneration()
|
||
↓
|
||
iverilogRunner.generateVCD()
|
||
↓
|
||
生成 VCD 文件
|
||
↓
|
||
发送 vcdGenerated 消息到前端
|
||
↓
|
||
webviewContent 接收消息
|
||
↓
|
||
创建波形预览卡片
|
||
```
|
||
|
||
### 2. 波形预览加载流程
|
||
```
|
||
createWaveformPreview() 创建卡片
|
||
↓
|
||
loadMiniWaveform() 请求 VCD 信息
|
||
↓
|
||
发送 getVCDInfo 消息到后端
|
||
↓
|
||
ICHelperPanel 接收消息
|
||
↓
|
||
getVCDFileInfo() 读取并解析 VCD 文件
|
||
↓
|
||
parseVCDSignals() 解析信号数据
|
||
↓
|
||
发送 vcdInfo 消息到前端
|
||
↓
|
||
renderWaveformInfo() 渲染波形
|
||
↓
|
||
drawRealWaveform() 绘制 SVG 波形图
|
||
```
|
||
|
||
### 3. 展开查看流程
|
||
```
|
||
用户点击"展开查看"按钮
|
||
↓
|
||
openFullWaveform() 发送消息
|
||
↓
|
||
发送 openWaveformViewer 消息到后端
|
||
↓
|
||
ICHelperPanel 接收消息
|
||
↓
|
||
VCDViewerPanel.createOrShow()
|
||
↓
|
||
打开完整波形查看器窗口
|
||
```
|
||
|
||
---
|
||
|
||
## 样式说明
|
||
|
||
### CSS 类名
|
||
- `.waveform-preview` - 波形预览卡片容器
|
||
- `.waveform-preview-header` - 卡片头部
|
||
- `.waveform-preview-title` - 标题区域
|
||
- `.waveform-expand-btn` - 展开按钮
|
||
- `.waveform-preview-content` - 内容区域
|
||
- `.waveform-mini-viewer` - 波形显示容器
|
||
- `.waveform-loading` - 加载提示
|
||
|
||
### 波形绘制
|
||
- **单比特信号**:使用 SVG `<path>` 绘制数字波形
|
||
- 高电平:y = 顶部
|
||
- 低电平:y = 底部
|
||
- 垂直跳变表示信号变化
|
||
|
||
- **多比特信号**:使用 SVG `<path>` 绘制总线波形
|
||
- 梯形表示数据变化
|
||
- 中间线表示稳定状态
|
||
|
||
- **颜色方案**:
|
||
- 第1个信号:蓝色 (`var(--vscode-charts-blue)`)
|
||
- 第2个信号:绿色 (`var(--vscode-charts-green)`)
|
||
- 第3个信号:橙色 (`var(--vscode-charts-orange)`)
|
||
|
||
---
|
||
|
||
## 配置参数
|
||
|
||
### 可调整参数
|
||
|
||
**在 `ICHelperPanel.ts` 中:**
|
||
```typescript
|
||
const signals = parseVCDSignals(content, 3); // 解析前3个信号
|
||
```
|
||
- 修改数字可以改变显示的信号数量
|
||
|
||
**在 `parseVCDSignals()` 中:**
|
||
```typescript
|
||
if (values.length >= 50) {
|
||
break; // 限制最多50个采样点
|
||
}
|
||
```
|
||
- 修改数字可以改变采样点数量
|
||
|
||
**在 `drawRealWaveform()` 中:**
|
||
```typescript
|
||
const signalHeight = 20; // 信号高度
|
||
const signalSpacing = 30; // 信号间距
|
||
const leftMargin = 80; // 左边距(信号名称区域)
|
||
const rightMargin = 20; // 右边距
|
||
```
|
||
- 修改这些参数可以调整波形显示样式
|
||
|
||
---
|
||
|
||
## 性能优化
|
||
|
||
1. **限制信号数量**:只解析前 3 个信号
|
||
2. **限制采样点**:每个信号最多 50 个采样点
|
||
3. **轻量级渲染**:使用 SVG 而不是 Canvas
|
||
4. **按需加载**:只在需要时读取和解析 VCD 文件
|
||
|
||
---
|
||
|
||
## 错误处理
|
||
|
||
### 文件不存在
|
||
```typescript
|
||
if (!fs.existsSync(vcdFilePath)) {
|
||
// 返回错误信息
|
||
vcdInfo: {
|
||
signalCount: 'N/A',
|
||
timeRange: 'N/A',
|
||
fileSize: 'N/A',
|
||
error: '文件不存在'
|
||
}
|
||
}
|
||
```
|
||
|
||
### 解析失败
|
||
```typescript
|
||
try {
|
||
// 解析逻辑
|
||
} catch (error) {
|
||
console.error('解析 VCD 信号数据失败:', error);
|
||
return []; // 返回空数组
|
||
}
|
||
```
|
||
|
||
### 无信号数据
|
||
```typescript
|
||
if (!signals || signals.length === 0) {
|
||
return `<svg>无波形数据</svg>`;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 未来扩展
|
||
|
||
### 可能的改进方向
|
||
|
||
1. **交互功能**
|
||
- 鼠标悬停显示信号值
|
||
- 点击信号高亮显示
|
||
- 缩放和平移功能
|
||
|
||
2. **显示优化**
|
||
- 自动选择最有代表性的信号
|
||
- 智能采样(保留关键变化点)
|
||
- 支持更多信号类型(模拟信号等)
|
||
|
||
3. **性能优化**
|
||
- 使用 Web Worker 解析大文件
|
||
- 虚拟滚动显示大量信号
|
||
- 缓存解析结果
|
||
|
||
4. **功能增强**
|
||
- 支持信号搜索和过滤
|
||
- 导出波形图片
|
||
- 比较多个 VCD 文件
|
||
|
||
---
|
||
|
||
## 调试技巧
|
||
|
||
### 查看消息流
|
||
在浏览器开发者工具中查看 `vscode.postMessage()` 的调用:
|
||
```javascript
|
||
console.log('发送消息:', message);
|
||
vscode.postMessage(message);
|
||
```
|
||
|
||
### 查看解析结果
|
||
在 `parseVCDSignals()` 中添加日志:
|
||
```typescript
|
||
console.log('解析到的信号:', signals);
|
||
```
|
||
|
||
### 查看 SVG 输出
|
||
在 `drawRealWaveform()` 中添加日志:
|
||
```javascript
|
||
console.log('SVG 内容:', svgContent);
|
||
```
|
||
|
||
---
|
||
|
||
## 相关文件
|
||
|
||
- `src/utils/iverilogRunner.ts` - VCD 文件生成
|
||
- `src/panels/VCDViewerPanel.ts` - 完整波形查看器
|
||
- `media/vcdrom/` - VCDrom 波形查看库
|
||
|
||
---
|
||
|
||
## 版本历史
|
||
|
||
### v1.0 (当前版本)
|
||
- ✅ 创建独立的波形预览组件
|
||
- ✅ 解析 VCD 文件中的真实信号数据
|
||
- ✅ 绘制单比特和多比特信号波形
|
||
- ✅ 支持展开查看完整波形
|
||
- ✅ 轻量级预览,快速加载
|
||
|
||
---
|
||
|
||
## 总结
|
||
|
||
波形预览功能通过以下文件协同工作:
|
||
|
||
1. **`waveformPreviewContent.ts`** - 组件核心逻辑
|
||
2. **`webviewContent.ts`** - 集成到主页面
|
||
3. **`messageHandler.ts`** - 处理 VCD 生成
|
||
4. **`ICHelperPanel.ts`** - 解析 VCD 数据和消息处理
|
||
|
||
整个功能采用模块化设计,易于维护和扩展。
|