/** * VCD 文件处理模块 * 功能:VCD 文件信息获取和信号解析 * 依赖:vscode, fs * 使用场景:波形查看器相关功能 */ import * as vscode from "vscode"; export async function getVCDFileInfo( panel: vscode.WebviewPanel, vcdFilePath: string, containerId: string, ) { try { const fs = require("fs"); if (!fs.existsSync(vcdFilePath)) { panel.webview.postMessage({ command: "vcdInfo", containerId: containerId, vcdInfo: { signalCount: "N/A", timeRange: "N/A", fileSize: "N/A", error: "文件不存在", }, }); return; } const stats = fs.statSync(vcdFilePath); const fileSizeKB = stats.size / 1024; const fileSize = fileSizeKB < 1024 ? `${fileSizeKB.toFixed(2)} KB` : `${(fileSizeKB / 1024).toFixed(2)} MB`; const content = fs.readFileSync(vcdFilePath, "utf-8"); const varMatches = content.match(/\$var/g); const signalCount = varMatches ? varMatches.length : 0; let timeRange = "N/A"; const timeMatch = content.match(/#(\d+)/g); if (timeMatch && timeMatch.length > 0) { const times = timeMatch.map((t: string) => parseInt(t.substring(1))); const minTime = Math.min(...times); const maxTime = Math.max(...times); timeRange = `${minTime} - ${maxTime}`; } const signals = parseVCDSignals(content, 3); panel.webview.postMessage({ command: "vcdInfo", containerId: containerId, vcdInfo: { signalCount: signalCount.toString(), timeRange: timeRange, fileSize: fileSize, signals: signals, }, }); } catch (error) { console.error("获取 VCD 文件信息失败:", error); panel.webview.postMessage({ command: "vcdInfo", containerId: containerId, vcdInfo: { signalCount: "N/A", timeRange: "N/A", fileSize: "N/A", error: error instanceof Error ? error.message : "未知错误", }, }); } } function parseVCDSignals(content: string, maxSignals: number = 3) { const signals: Array<{ name: string; identifier: string; width: number; values: Array<{ time: number; value: string }>; }> = []; try { const varRegex = /\$var\s+(\w+)\s+(\d+)\s+(\S+)\s+([^\$]+?)\s+\$end/g; let match; const signalDefs: Array<{ name: string; identifier: string; width: number; }> = []; while ( (match = varRegex.exec(content)) !== null && signalDefs.length < maxSignals ) { const width = parseInt(match[2]); const identifier = match[3]; const name = match[4].trim(); signalDefs.push({ name, identifier, width }); } const dumpvarsIndex = content.indexOf("$dumpvars"); if (dumpvarsIndex === -1) { return signals; } const dataSection = content.substring(dumpvarsIndex); for (const signalDef of signalDefs) { const values: Array<{ time: number; value: string }> = []; let currentTime = 0; const lines = dataSection.split("\n"); for (const line of lines) { const trimmedLine = line.trim(); if (trimmedLine.startsWith("#")) { currentTime = parseInt(trimmedLine.substring(1)); continue; } if (signalDef.width === 1) { const singleBitMatch = trimmedLine.match( new RegExp(`^([01xz])${signalDef.identifier}$`), ); if (singleBitMatch) { values.push({ time: currentTime, value: singleBitMatch[1] }); } } else { const multiBitMatch = trimmedLine.match( new RegExp(`^b([01xz]+)\\s+${signalDef.identifier}$`), ); if (multiBitMatch) { values.push({ time: currentTime, value: multiBitMatch[1] }); } } if (values.length >= 50) { break; } } signals.push({ name: signalDef.name, identifier: signalDef.identifier, width: signalDef.width, values: values, }); } } catch (error) { console.error("解析 VCD 信号数据失败:", error); } return signals; }