10 KiB
10 KiB
波形预览功能技术文档
功能概述
在对话界面中显示 VCD 波形文件的预览卡片,用户可以查看前几个信号的真实波形,并通过"展开查看"按钮打开完整的波形查看器。
功能流程
用户输入"生成VCD"命令
↓
系统执行 iverilog 编译和仿真
↓
生成 VCD 文件
↓
在对话界面显示波形预览卡片
├─ 显示真实的波形图(前3个信号)
├─ 显示信号名称和波形
└─ "展开查看"按钮
↓
点击"展开查看"按钮
↓
打开完整的 VCDViewerPanel 波形查看器
文件结构
1. src/views/waveformPreviewContent.ts
功能: 波形预览组件的独立模块
导出函数:
getWaveformPreviewContent()- 返回波形预览组件的 CSS 样式getWaveformPreviewScript()- 返回波形预览组件的 JavaScript 代码
主要功能:
- 创建波形预览卡片的 HTML 结构
- 从 VCD 文件中提取真实信号数据
- 使用 SVG 绘制波形图
- 单比特信号:绘制数字波形(高/低电平)
- 多比特信号:绘制总线波形(梯形)
- 处理"展开查看"按钮点击事件
关键函数:
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消息处理逻辑
消息处理:
case 'vcdGenerated':
// VCD 文件生成成功,显示带波形预览的消息
- 创建消息 div
- 添加成功消息文本
- 调用 addWaveformPreviewToMessage() 添加波形预览卡片
case 'vcdInfo':
// 接收到 VCD 文件信息,渲染波形预览
- 调用 renderWaveformInfo() 渲染波形
3. src/utils/messageHandler.ts
功能: 处理用户消息和 VCD 生成请求
修改内容:
- 导入
path模块 - 修改 VCD 生成成功后的消息发送逻辑
关键代码:
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 文件信息并解析信号数据
处理流程:
- 检查文件是否存在
- 获取文件大小
- 读取 VCD 文件内容
- 解析信号数量
- 解析时间范围
- 调用
parseVCDSignals()解析前 3 个信号的数据 - 发送
vcdInfo消息回前端
返回数据结构:
{
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 文件中的信号数据
处理流程:
- 使用正则表达式解析信号定义部分(
$var ... $end) - 提取信号名称、标识符、位宽
- 找到数据变化部分(
$dumpvars之后) - 解析每个信号的值变化
- 单比特信号:格式
0!或1! - 多比特信号:格式
b1010 !
- 单比特信号:格式
- 限制最多 50 个采样点(避免数据过多)
- 返回信号数据数组
VCD 文件格式示例:
$var wire 1 ! clk $end
$var wire 8 " data $end
$dumpvars
0!
b00000000 "
#10
1!
#20
0!
b00000001 "
消息处理:
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))
- 第1个信号:蓝色 (
配置参数
可调整参数
在 ICHelperPanel.ts 中:
const signals = parseVCDSignals(content, 3); // 解析前3个信号
- 修改数字可以改变显示的信号数量
在 parseVCDSignals() 中:
if (values.length >= 50) {
break; // 限制最多50个采样点
}
- 修改数字可以改变采样点数量
在 drawRealWaveform() 中:
const signalHeight = 20; // 信号高度
const signalSpacing = 30; // 信号间距
const leftMargin = 80; // 左边距(信号名称区域)
const rightMargin = 20; // 右边距
- 修改这些参数可以调整波形显示样式
性能优化
- 限制信号数量:只解析前 3 个信号
- 限制采样点:每个信号最多 50 个采样点
- 轻量级渲染:使用 SVG 而不是 Canvas
- 按需加载:只在需要时读取和解析 VCD 文件
错误处理
文件不存在
if (!fs.existsSync(vcdFilePath)) {
// 返回错误信息
vcdInfo: {
signalCount: 'N/A',
timeRange: 'N/A',
fileSize: 'N/A',
error: '文件不存在'
}
}
解析失败
try {
// 解析逻辑
} catch (error) {
console.error('解析 VCD 信号数据失败:', error);
return []; // 返回空数组
}
无信号数据
if (!signals || signals.length === 0) {
return `<svg>无波形数据</svg>`;
}
未来扩展
可能的改进方向
-
交互功能
- 鼠标悬停显示信号值
- 点击信号高亮显示
- 缩放和平移功能
-
显示优化
- 自动选择最有代表性的信号
- 智能采样(保留关键变化点)
- 支持更多信号类型(模拟信号等)
-
性能优化
- 使用 Web Worker 解析大文件
- 虚拟滚动显示大量信号
- 缓存解析结果
-
功能增强
- 支持信号搜索和过滤
- 导出波形图片
- 比较多个 VCD 文件
调试技巧
查看消息流
在浏览器开发者工具中查看 vscode.postMessage() 的调用:
console.log('发送消息:', message);
vscode.postMessage(message);
查看解析结果
在 parseVCDSignals() 中添加日志:
console.log('解析到的信号:', signals);
查看 SVG 输出
在 drawRealWaveform() 中添加日志:
console.log('SVG 内容:', svgContent);
相关文件
src/utils/iverilogRunner.ts- VCD 文件生成src/panels/VCDViewerPanel.ts- 完整波形查看器media/vcdrom/- VCDrom 波形查看库
版本历史
v1.0 (当前版本)
- ✅ 创建独立的波形预览组件
- ✅ 解析 VCD 文件中的真实信号数据
- ✅ 绘制单比特和多比特信号波形
- ✅ 支持展开查看完整波形
- ✅ 轻量级预览,快速加载
总结
波形预览功能通过以下文件协同工作:
waveformPreviewContent.ts- 组件核心逻辑webviewContent.ts- 集成到主页面messageHandler.ts- 处理 VCD 生成ICHelperPanel.ts- 解析 VCD 数据和消息处理
整个功能采用模块化设计,易于维护和扩展。