From f200d90fc0897c98f4e0c0cdfbb71dd47461660f Mon Sep 17 00:00:00 2001 From: SikongJueluo Date: Tue, 29 Jul 2025 14:57:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=95=B0=E5=80=BC?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E7=9A=84=E6=B3=A2=E5=BD=A2=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WaveformDisplay/WaveformDisplay.vue | 236 ++++++++++++------ src/views/Project/Debugger.vue | 2 +- 2 files changed, 155 insertions(+), 83 deletions(-) diff --git a/src/components/WaveformDisplay/WaveformDisplay.vue b/src/components/WaveformDisplay/WaveformDisplay.vue index e73f4c3..d443c08 100644 --- a/src/components/WaveformDisplay/WaveformDisplay.vue +++ b/src/components/WaveformDisplay/WaveformDisplay.vue @@ -39,6 +39,7 @@ import { DataZoomComponent, AxisPointerComponent, ToolboxComponent, + MarkLineComponent, } from "echarts/components"; import { CanvasRenderer } from "echarts/renderers"; import type { ComposeOption } from "echarts/core"; @@ -48,6 +49,7 @@ import type { TooltipComponentOption, GridComponentOption, DataZoomComponentOption, + MarkLineComponentOption, } from "echarts/components"; import type { ToolboxComponentOption, @@ -66,6 +68,7 @@ use([ DataZoomComponent, LineChart, CanvasRenderer, + MarkLineComponent, ]); type EChartsOption = ComposeOption< @@ -75,6 +78,7 @@ type EChartsOption = ComposeOption< | GridComponentOption | DataZoomComponentOption | LineSeriesOption + | MarkLineComponentOption >; const analyzer = useRequiredInjection(useWaveformManager); @@ -90,7 +94,9 @@ const option = computed((): EChartsOption => { if (isUndefined(analyzer.logicData.value)) return {}; // 只获取启用的通道,使用y数据结构 - const enabledChannels = analyzer.logicData.value.y.filter(channel => channel.enabled); + const enabledChannels = analyzer.logicData.value.y.filter( + (channel) => channel.enabled, + ); const enabledChannelIndices = analyzer.logicData.value.y .map((channel, index) => (channel.enabled ? index : -1)) .filter((index) => index !== -1); @@ -149,77 +155,141 @@ const option = computed((): EChartsOption => { // 创建系列数据 const series: LineSeriesOption[] = []; - enabledChannelIndices.forEach((originalIndex: number, displayIndex: number) => { - const channel = analyzer.logicData.value!.y[originalIndex]; - if (channel.type === "logic") { - // logic类型,原样显示 - series.push({ - name: channel.name, - type: "line", - data: channel.value.map( - (value: number) => value + displayIndex * channelSpacing + 0.2, - ), - step: "end", - lineStyle: { - width: 2, - color: channel.color, - }, - areaStyle: { - opacity: 0.3, - origin: displayIndex * channelSpacing, - color: channel.color, - }, - symbol: "none", - sampling: "lttb", - animation: false, - }); - } else if (channel.type === "number") { - // number类型,VCD仿真样式:两个线条(1和0),变化时有斜率(过渡点),无areaStyle - const values = channel.value; - const xArr = analyzer.logicData.value!.x; - // 构造带过渡的点序列 - function buildVcdLine(valArr: number[], high: number, low: number) { - const points: {x: number, y: number}[] = []; - let lastValue = high; - points.push({x: xArr[0], y: lastValue}); - for (let i = 1; i < valArr.length; i++) { - const v = valArr[i] !== valArr[i-1] ? (lastValue === high ? low : high) : lastValue; - points.push({x: xArr[i], y: v}); - lastValue = v; + enabledChannelIndices.forEach( + (originalIndex: number, displayIndex: number) => { + const channel = analyzer.logicData.value!.y[originalIndex]; + if (channel.type === "logic") { + // logic类型,原样显示 + series.push({ + name: channel.name, + type: "line", + data: channel.value.map( + (value: number) => value + displayIndex * channelSpacing + 0.2, + ), + step: "end", + lineStyle: { + width: 2, + color: channel.color, + }, + areaStyle: { + opacity: 0.3, + origin: displayIndex * channelSpacing, + color: channel.color, + }, + symbol: "none", + sampling: "lttb", + animation: false, + }); + } else if (channel.type === "number") { + const values = channel.value; + const xArr = analyzer.logicData.value!.x; + // 构造带过渡的点序列 + function buildVcdLine(valArr: number[], high: number, low: number) { + const points: { x: number; y: number }[] = []; + let lastValue = high; + points.push({ x: xArr[0], y: lastValue }); + for (let i = 1; i < valArr.length; i++) { + const v = + valArr[i] !== valArr[i - 1] + ? lastValue === high + ? low + : high + : lastValue; + points.push({ x: xArr[i], y: v }); + lastValue = v; + } + return points.map((p) => p.y); } - // 返回y数组,x由category轴控制 - return points.map(p => p.y); + + // 计算变化点区间 + function buildMarkLines(valArr: number[], yBase: number) { + const markLines: any[] = []; + let lastValue = valArr[0]; + let lastIdx = 0; + // 格式化函数 + function formatValue(val: number) { + if (channel.base === "hex") return "0x" + val.toString(16).toUpperCase(); + if (channel.base === "bin") return "0b" + val.toString(2); + return val.toString(); + } + for (let i = 1; i <= valArr.length; i++) { + if (i === valArr.length || valArr[i] !== lastValue) { + markLines.push([ + { + xAxis: lastIdx, + yAxis: yBase, + label: { + formatter: formatValue(lastValue), + position: "insideMiddle", + color: channel.color, + fontSize: 18, + opacity: 1, + }, + lineStyle: { + opacity: 0, + }, + }, + { + xAxis: i - 1, + yAxis: yBase, + lineStyle: { + opacity: 0, + }, + }, + ]); + lastValue = valArr[i]; + lastIdx = i; + } + } + return markLines; + } + + // 1线条 + series.push({ + name: channel.name + "_1", + type: "line", + data: buildVcdLine( + values, + displayIndex * channelSpacing + 1, + displayIndex * channelSpacing, + ), + step: false, + lineStyle: { + width: 2, + color: channel.color, + }, + symbol: "none", + sampling: "lttb", + animation: false, + // 添加markLine + markLine: { + data: buildMarkLines(values, displayIndex * channelSpacing + 0.5), + emphasis: { + disabled: true, + }, + }, + }); + // 0线条 + series.push({ + name: channel.name + "_0", + type: "line", + data: buildVcdLine( + values, + displayIndex * channelSpacing, + displayIndex * channelSpacing + 1, + ), + step: false, + lineStyle: { + width: 2, + color: channel.color, + }, + symbol: "none", + sampling: "lttb", + animation: false, + }); } - // 1线条 - series.push({ - name: channel.name + "_1", - type: "line", - data: buildVcdLine(values, displayIndex * channelSpacing + 1, displayIndex * channelSpacing), - step: false, // 关闭step,允许斜率 - lineStyle: { - width: 2, - color: channel.color, - }, - symbol: "none", - sampling: "lttb", - animation: false, - }); - // 0线条 - series.push({ - name: channel.name + "_0", - type: "line", - data: buildVcdLine(values, displayIndex * channelSpacing, displayIndex * channelSpacing + 1), - step: false, - lineStyle: { - width: 2, - color: channel.color, - }, - symbol: "none", - sampling: "lttb", - animation: false, - }); - } - }); + }, + ); return { animation: false, @@ -237,18 +307,20 @@ const option = computed((): EChartsOption => { const timeValue = analyzer.logicData.value!.x[params[0].dataIndex]; const dataIndex = params[0].dataIndex; let tooltip = `Time: ${timeValue.toFixed(3)}${analyzer.logicData.value!.xUnit}
`; - enabledChannelIndices.forEach((originalIndex: number, displayIndex: number) => { - const channel = analyzer.logicData.value!.y[originalIndex]; - if (channel.type === "logic") { - const channelName = channel.name; - const originalValue = channel.value[dataIndex]; - tooltip += `${channelName}: ${originalValue}
`; - } else if (channel.type === "number") { - const channelName = channel.name; - const originalValue = channel.value[dataIndex]; - tooltip += `${channelName}: ${originalValue}
`; - } - }); + enabledChannelIndices.forEach( + (originalIndex: number, displayIndex: number) => { + const channel = analyzer.logicData.value!.y[originalIndex]; + if (channel.type === "logic") { + const channelName = channel.name; + const originalValue = channel.value[dataIndex]; + tooltip += `${channelName}: ${originalValue}
`; + } else if (channel.type === "number") { + const channelName = channel.name; + const originalValue = channel.value[dataIndex]; + tooltip += `${channelName}: ${originalValue}
`; + } + }, + ); return tooltip; } return ""; diff --git a/src/views/Project/Debugger.vue b/src/views/Project/Debugger.vue index 786ff44..be6e578 100644 --- a/src/views/Project/Debugger.vue +++ b/src/views/Project/Debugger.vue @@ -1,6 +1,6 @@