新增功能: - 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: 打包脚本
146 lines
3.7 KiB
TypeScript
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}`
|
|
};
|
|
}
|
|
}
|