feat: 支持多VCD文件生成功能

- iverilogRunner新增generateMultiVCD函数
- toolExecutor处理dumpModules参数
- api.ts扩展SimulationArgs接口
- messageArea支持多波形预览
This commit is contained in:
XiaoFeng
2026-01-10 16:45:39 +08:00
parent 5c19be22d3
commit 15a1de3a90
4 changed files with 299 additions and 26 deletions

View File

@ -675,6 +675,29 @@ export function getMessageAreaScript(): string {
${getPlanCardScript()}
// 解析多 VCD 文件路径
function parseMultiVcdPaths(toolResult) {
if (!toolResult) return [];
const result = String(toolResult);
// 匹配 "- moduleName: path" 格式
const vcdListMatch = result.match(/VCD 文件列表:[\\s\\S]*?(?=\\n\\n|$)/);
if (!vcdListMatch) return [];
const paths = [];
const lineRegex = /- (\\w+): ([^\\n]+)/g;
let match;
while ((match = lineRegex.exec(vcdListMatch[0])) !== null) {
const name = match[1];
const pathOrError = match[2].trim();
// 跳过失败的条目
if (!pathOrError.startsWith('失败')) {
paths.push({ name: name + '.vcd', path: pathOrError });
}
}
return paths;
}
// 获取工具图标
function getToolIcon(toolName) {
const iconMap = {
@ -1034,19 +1057,30 @@ export function getMessageAreaScript(): string {
// 如果是仿真工具且成功完成,尝试添加波形预览
if (segment.toolName === 'simulation' && segment.toolStatus === 'success') {
// 优先使用显式提供的路径,否则从结果文本中解析
let vcdPath = segment.vcdFilePath;
if (!vcdPath && segment.toolResult) {
const match = String(segment.toolResult).match(/路径\s*:\s*(.+)/);
if (match && match[1]) {
vcdPath = match[1].trim();
}
}
// 尝试解析多个 VCD 文件(多 VCD 模式)
const vcdPaths = parseMultiVcdPaths(segment.toolResult);
if (vcdPath) {
const fileName = segment.fileName || vcdPath.split(/[\\\\\/]/).pop() || 'waveform.vcd';
const waveformPreview = createWaveformPreview(vcdPath, fileName);
segmentDiv.appendChild(waveformPreview);
if (vcdPaths.length > 0) {
// 多 VCD 模式:为每个文件创建预览
vcdPaths.forEach(vcdInfo => {
const waveformPreview = createWaveformPreview(vcdInfo.path, vcdInfo.name);
segmentDiv.appendChild(waveformPreview);
});
} else {
// 单 VCD 模式(兼容旧逻辑)
let vcdPath = segment.vcdFilePath;
if (!vcdPath && segment.toolResult) {
const match = String(segment.toolResult).match(/路径\s*:\s*(.+)/);
if (match && match[1]) {
vcdPath = match[1].trim();
}
}
if (vcdPath) {
const fileName = segment.fileName || vcdPath.split(/[\\\\\/]/).pop() || 'waveform.vcd';
const waveformPreview = createWaveformPreview(vcdPath, fileName);
segmentDiv.appendChild(waveformPreview);
}
}
}
@ -1281,19 +1315,30 @@ export function getMessageAreaScript(): string {
// 如果是仿真工具且成功完成,尝试添加波形预览
if (segment.toolName === 'simulation' && segment.toolStatus === 'success') {
// 优先使用显式提供的路径,否则从结果文本中解析
let vcdPath = segment.vcdFilePath;
if (!vcdPath && segment.toolResult) {
const match = String(segment.toolResult).match(/路径\s*:\s*(.+)/);
if (match && match[1]) {
vcdPath = match[1].trim();
}
}
// 尝试解析多个 VCD 文件(多 VCD 模式)
const vcdPaths = parseMultiVcdPaths(segment.toolResult);
if (vcdPath) {
const fileName = segment.fileName || vcdPath.split(/[\\\\\/]/).pop() || 'waveform.vcd';
const waveformPreview = createWaveformPreview(vcdPath, fileName);
segmentDiv.appendChild(waveformPreview);
if (vcdPaths.length > 0) {
// 多 VCD 模式:为每个文件创建预览
vcdPaths.forEach(vcdInfo => {
const waveformPreview = createWaveformPreview(vcdInfo.path, vcdInfo.name);
segmentDiv.appendChild(waveformPreview);
});
} else {
// 单 VCD 模式(兼容旧逻辑)
let vcdPath = segment.vcdFilePath;
if (!vcdPath && segment.toolResult) {
const match = String(segment.toolResult).match(/路径\s*:\s*(.+)/);
if (match && match[1]) {
vcdPath = match[1].trim();
}
}
if (vcdPath) {
const fileName = segment.fileName || vcdPath.split(/[\\\\\/]/).pop() || 'waveform.vcd';
const waveformPreview = createWaveformPreview(vcdPath, fileName);
segmentDiv.appendChild(waveformPreview);
}
}
}