Files
IC-Coder-Plugin/src/utils/waveformTracer.ts
XiaoFeng ada4806493 feat: 集成 waveform_trace 波形调试工具
新增功能:
- waveformTracer.ts: 调用 waveform_trace.exe 的工具实现
- toolExecutor.ts: 添加 waveform_trace 工具分发
- types/api.ts: 添加 WaveformTraceArgs 类型定义

工具源码 (tools/waveform_trace/src/):
- AST 解析 + BFS 信号追踪
- VCD 波形解析
- 修复通用 testbench 支持

配置文件:
- .gitignore: 排除 exe 和打包产物
- .vscodeignore: 发布时排除源码
- build.bat/build.sh: 打包脚本
2026-01-05 18:18:57 +08:00

146 lines
3.7 KiB
TypeScript

/**
* 波形追踪工具
* 调用 PyInstaller 打包的 waveform_trace 可执行文件
*/
import { spawn } from 'child_process';
import * as path from 'path';
import * as fs from 'fs';
import * as vscode from 'vscode';
/**
* 波形追踪参数
*/
export interface WaveformTraceArgs {
/** Verilog 源文件路径(相对于项目根目录) */
verilogPath: string;
/** VCD 波形文件路径(相对于项目根目录) */
vcdPath: string;
/** 仿真工具的输出字符串(包含 mismatch 信息) */
simOutput: string;
/** BFS 回溯层数,默认 2 */
traceLevel?: number;
}
/**
* 执行波形追踪
* @param args 追踪参数
* @param context 执行上下文
* @returns 追踪结果字符串
*/
export async function executeWaveformTrace(
args: WaveformTraceArgs,
context: { extensionPath: string }
): Promise<string> {
// 获取可执行文件路径
const tracerPath = getWaveformTracerPath(context.extensionPath);
// 检查可执行文件是否存在
if (!fs.existsSync(tracerPath)) {
throw new Error(
`waveform_trace 工具未安装: ${tracerPath}\n` +
'请确保插件包含 tools/waveform_trace/bin/ 目录'
);
}
// 获取工作区路径
const workspaceFolders = vscode.workspace.workspaceFolders;
if (!workspaceFolders || workspaceFolders.length === 0) {
throw new Error('请先打开一个工作区');
}
const workspacePath = workspaceFolders[0].uri.fsPath;
// 解析路径(支持相对路径)
const verilogAbsPath = path.isAbsolute(args.verilogPath)
? args.verilogPath
: path.join(workspacePath, args.verilogPath);
const vcdAbsPath = path.isAbsolute(args.vcdPath)
? args.vcdPath
: path.join(workspacePath, args.vcdPath);
// 验证文件存在
if (!fs.existsSync(verilogAbsPath)) {
throw new Error(`Verilog 文件不存在: ${args.verilogPath}`);
}
if (!fs.existsSync(vcdAbsPath)) {
throw new Error(`VCD 文件不存在: ${args.vcdPath}`);
}
// 调用可执行文件
return new Promise((resolve, reject) => {
const child = spawn(tracerPath, [
'--verilog', verilogAbsPath,
'--vcd', vcdAbsPath,
'--sim-output', args.simOutput,
'--trace-level', String(args.traceLevel || 2),
'--output-format', 'text'
], {
windowsHide: true,
cwd: workspacePath,
shell: false
});
let stdout = '';
let stderr = '';
child.stdout.on('data', (data: Buffer) => {
stdout += data.toString();
});
child.stderr.on('data', (data: Buffer) => {
stderr += data.toString();
});
child.on('close', (code: number | null) => {
if (code === 0) {
resolve(stdout);
} else {
reject(new Error(
`waveform_trace 执行失败 (code=${code}):\n${stderr || stdout}`
));
}
});
child.on('error', (error: Error) => {
reject(new Error(`waveform_trace 启动失败: ${error.message}`));
});
});
}
/**
* 获取 waveform_trace 可执行文件路径
*/
function getWaveformTracerPath(extensionPath: string): string {
const platform = process.platform;
let binName = 'waveform_trace';
if (platform === 'win32') {
binName = 'waveform_trace.exe';
}
return path.join(extensionPath, 'tools', 'waveform_trace', 'bin', binName);
}
/**
* 检查 waveform_trace 工具是否可用
*/
export function checkWaveformTraceAvailable(extensionPath: string): {
available: boolean;
message: string;
path?: string;
} {
const tracerPath = getWaveformTracerPath(extensionPath);
if (fs.existsSync(tracerPath)) {
return {
available: true,
message: 'waveform_trace 工具可用',
path: tracerPath
};
} else {
return {
available: false,
message: `waveform_trace 工具未找到: ${tracerPath}`
};
}
}