完成 vec 模式下的 0 绘制
This commit is contained in:
parent
b2e4fb8a8a
commit
0a36a28a57
@ -56,6 +56,8 @@ export default {
|
|||||||
document.body.style.setProperty('--el-color-info', 'var(--foreground)');
|
document.body.style.setProperty('--el-color-info', 'var(--foreground)');
|
||||||
document.body.style.setProperty('--el-color-info-light-8', 'var(--vscode-focusBorder)');
|
document.body.style.setProperty('--el-color-info-light-8', 'var(--vscode-focusBorder)');
|
||||||
document.body.style.setProperty('--el-bg-color-overlay', 'transplant');
|
document.body.style.setProperty('--el-bg-color-overlay', 'transplant');
|
||||||
|
// document.body.style.setProperty('--el-color-white', 'var(--background)');
|
||||||
|
|
||||||
|
|
||||||
// signal height
|
// signal height
|
||||||
document.body.style.setProperty('--display-signal-info-height', globalSetting.displaySignalHeight + 'px');
|
document.body.style.setProperty('--display-signal-info-height', globalSetting.displaySignalHeight + 'px');
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- <VerticalCursor></VerticalCursor> -->
|
<!-- <VerticalCursor></VerticalCursor> -->
|
||||||
<!-- <TimeScale></TimeScale> -->
|
<!-- <TimeScale></TimeScale> -->
|
||||||
<div class="vcd-render-wrapper" >
|
<div class="vcd-render-wrapper" @click="updateWireCurrentValue()">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -10,6 +10,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { reactive, ref } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import { emitter, globalLookup, globalSetting } from '@/hook/global';
|
import { emitter, globalLookup, globalSetting } from '@/hook/global';
|
||||||
|
import { updateWireCurrentValue } from '@/hook/utils';
|
||||||
|
|
||||||
import VerticalCursor from '@/components/render/cursor.vue';
|
import VerticalCursor from '@/components/render/cursor.vue';
|
||||||
import TimeScale from '@/components/render/time-scale.vue';
|
import TimeScale from '@/components/render/time-scale.vue';
|
||||||
@ -22,8 +23,11 @@ export default {
|
|||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
globalLookup
|
globalLookup,
|
||||||
|
updateWireCurrentValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,11 +131,15 @@ rect.wd-cursor-time {
|
|||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
text.xred {
|
text.common {
|
||||||
|
fill: var(--sidebar-item-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
text.high-impedance {
|
||||||
fill: hsl(0, 100%, 50%);
|
fill: hsl(0, 100%, 50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
text.zxviolet {
|
text.unknown {
|
||||||
fill: hsl(287, 100%, 67%);
|
fill: hsl(287, 100%, 67%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,11 @@
|
|||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="setting-option" style="width: 380px;">
|
||||||
|
<span class="option-title" style="width: 300px;">{{ t('wheel-zoom-ratio') }}</span>
|
||||||
|
<el-slider v-model="languageSetting.wheelZoomRatio" show-stops :min="1" :max="5"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
@ -145,4 +150,8 @@ export default {
|
|||||||
min-width: 80px;
|
min-width: 80px;
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-slider__button {
|
||||||
|
background-color: var(--background) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -8,9 +8,35 @@
|
|||||||
<span :class="makeSignalIconClass(signal)"></span>
|
<span :class="makeSignalIconClass(signal)"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="signal-info">
|
<div class="signal-info">
|
||||||
{{ signal.name }}
|
<div class="signal-info">
|
||||||
</div>
|
<el-tooltip
|
||||||
<div>
|
effect="dark"
|
||||||
|
:content="makeFullSignalNameDeps(signal)"
|
||||||
|
placement="top"
|
||||||
|
raw-content
|
||||||
|
>
|
||||||
|
<div class="signal-info-name">
|
||||||
|
{{ signal.name }}
|
||||||
|
</div></el-tooltip>
|
||||||
|
|
||||||
|
<div class="signal-info-width">
|
||||||
|
<div :class="signal.size > 1 ? 'signal-info-caption' : ''">
|
||||||
|
{{ makeSignalCaption(signal) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="signal-info-current-value-wrapper">
|
||||||
|
<span></span>
|
||||||
|
<el-tooltip
|
||||||
|
effect="dark"
|
||||||
|
:content="globalLookup.currentSignalValues[signal.link] + ''"
|
||||||
|
placement="top"
|
||||||
|
raw-content
|
||||||
|
><div class="signal-info-current-value">
|
||||||
|
{{ globalLookup.currentSignalValues[signal.link] }}
|
||||||
|
</div></el-tooltip>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -41,10 +67,41 @@ export default {
|
|||||||
return 'iconfont ' + makeIconClass(signal);
|
return 'iconfont ' + makeIconClass(signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeSignalCaption(signal) {
|
||||||
|
return signal.size === 1 ? '' : `${signal.size - 1}:0`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeFullSignalNameDeps(signal) {
|
||||||
|
const deps = [];
|
||||||
|
while (signal) {
|
||||||
|
if (signal.name && signal.type) {
|
||||||
|
deps.push(signal);
|
||||||
|
}
|
||||||
|
signal = signal.parent;
|
||||||
|
}
|
||||||
|
let htmlString = '';
|
||||||
|
for (let i = deps.length - 1; i >= 0; -- i) {
|
||||||
|
const mod = deps[i];
|
||||||
|
// const displayName = mod.name.length > 6 ? mod.name.substring(0, 6) + '...' : mod.name;
|
||||||
|
const iconClass = makeIconClass(mod);
|
||||||
|
const iconText = `<span class="iconfont ${iconClass}"></span> ${mod.name}`;
|
||||||
|
|
||||||
|
htmlString += iconText;
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
htmlString += '<div class="dep-arrow"></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
htmlString = '<div class="signal-info-tooltip-wrapper">' + htmlString + '</div>';
|
||||||
|
return htmlString;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
t,
|
t,
|
||||||
globalLookup,
|
globalLookup,
|
||||||
makeSignalIconClass,
|
makeSignalIconClass,
|
||||||
|
makeSignalCaption,
|
||||||
|
makeFullSignalNameDeps,
|
||||||
addSignal
|
addSignal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,11 +169,54 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.signal-info {
|
.signal-info {
|
||||||
|
width: 90%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.signal-info-name {
|
||||||
|
cursor: pointer;
|
||||||
|
max-width: 100px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signal-info-tooltip-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signal-info-width {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signal-info-caption {
|
||||||
|
width: fit-content;
|
||||||
|
color: var(--sidebar-item-text);
|
||||||
|
border-radius: .5em;
|
||||||
|
background-color: #7CA532;
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signal-info-current-value-wrapper {
|
||||||
|
margin-left: 10px;
|
||||||
|
width: 60px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signal-info-current-value {
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.signal-info::selection {
|
.signal-info::selection {
|
||||||
background: none;
|
background: none;
|
||||||
cursor: none;
|
cursor: none;
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
|
|
||||||
class LineDrawer {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {CanvasRenderingContext2D} ctx
|
|
||||||
*/
|
|
||||||
constructor(ctx) {
|
|
||||||
this.ctx = ctx;
|
|
||||||
this.lastColor = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
beginPath() {
|
|
||||||
this.ctx.beginPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {number} x
|
|
||||||
* @param {number} y
|
|
||||||
*/
|
|
||||||
moveTo(x, y) {
|
|
||||||
this.ctx.moveTo(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {number} x
|
|
||||||
* @param {number} y
|
|
||||||
* @param {string} color
|
|
||||||
*/
|
|
||||||
lineTo(x, y, color) {
|
|
||||||
const ctx = this.ctx;
|
|
||||||
ctx.lineTo(x, y);
|
|
||||||
|
|
||||||
if (this.lastColor === null) {
|
|
||||||
ctx.strokeStyle = color;
|
|
||||||
this.lastColor = color;
|
|
||||||
} else if (this.lastColor !== color) {
|
|
||||||
ctx.stroke();
|
|
||||||
ctx.strokeStyle = color;
|
|
||||||
this.lastColor = color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
LineDrawer
|
|
||||||
}
|
|
@ -12,6 +12,11 @@ const globalLookup = reactive({
|
|||||||
// 当前选中的某个 信号 的 数据。可复选。
|
// 当前选中的某个 信号 的 数据。可复选。
|
||||||
currentWires: new Set(),
|
currentWires: new Set(),
|
||||||
|
|
||||||
|
currentSignalValues: {},
|
||||||
|
|
||||||
|
// 当前 ns 数(或者 ps)
|
||||||
|
currentTime: 0,
|
||||||
|
|
||||||
// 模拟器的版本,比如如果使用 iverilog 那么就是 Icarus Verilog
|
// 模拟器的版本,比如如果使用 iverilog 那么就是 Icarus Verilog
|
||||||
version: '',
|
version: '',
|
||||||
// 创建时间
|
// 创建时间
|
||||||
@ -65,7 +70,7 @@ const globalSetting = reactive({
|
|||||||
searchMode: 'so', // so, mo, sm
|
searchMode: 'so', // so, mo, sm
|
||||||
searchScope: ['wire', 'reg', 'integer'],
|
searchScope: ['wire', 'reg', 'integer'],
|
||||||
displaySignalInfoScope: ['width', 'parent'],
|
displaySignalInfoScope: ['width', 'parent'],
|
||||||
|
wheelZoomRatio: 1,
|
||||||
minGridWidth: 300
|
minGridWidth: 300
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import { globalLookup, globalSetting, signalValues } from "./global";
|
import { globalLookup, globalSetting, signalValues } from "./global";
|
||||||
import { LineDrawer } from './canvas';
|
|
||||||
import { domContainer, pluginRenderTimeGrid, pluginRenderValues, mountTree,
|
import { domContainer, pluginRenderTimeGrid, pluginRenderValues, mountTree,
|
||||||
genOnWheel, genKeyHandler, keyBindo } from './wave-view';
|
genOnWheel, genKeyHandler, keyBindo } from './wave-view';
|
||||||
|
import { findCurrentSignalValue } from './utils';
|
||||||
import { createCodeMirrorState, mountCodeMirror6 } from 'waveql';
|
|
||||||
|
|
||||||
let mainRenderEl = null;
|
let mainRenderEl = null;
|
||||||
const canvasMap = new Map();
|
const canvasMap = new Map();
|
||||||
@ -22,227 +20,6 @@ function getMainRenderEl() {
|
|||||||
return mainRenderEl;
|
return mainRenderEl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {{
|
|
||||||
* time: BigInt,
|
|
||||||
* cmd: number,
|
|
||||||
* value?: BigInt,
|
|
||||||
* mask?: BigInt
|
|
||||||
* }} dataItem
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function isBlocked(dataItem) {
|
|
||||||
const mask = dataItem.mask;
|
|
||||||
if (mask && mask === 1n) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (mask && mask === 0n) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (mask === undefined && dataItem.cmd > 15) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {{
|
|
||||||
* kind: 'var' | 'scope',
|
|
||||||
* type: 'wire' | 'reg' | 'module',
|
|
||||||
* name: string,
|
|
||||||
* size: number,
|
|
||||||
* link: string
|
|
||||||
* }} signal
|
|
||||||
*/
|
|
||||||
function makeWaveCanvas(signal) {
|
|
||||||
const mainRender = getMainRenderEl();
|
|
||||||
const canvas = document.createElement('canvas');
|
|
||||||
canvas.id = 'wave-' + signal.link;
|
|
||||||
canvas.className = 'render-canvas';
|
|
||||||
canvas.width = document.body.clientWidth;
|
|
||||||
canvas.height = globalSetting.displaySignalHeight;
|
|
||||||
|
|
||||||
mainRender.appendChild(canvas);
|
|
||||||
canvasMap.set(signal, canvas);
|
|
||||||
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
const datas = signalValues[signal.link];
|
|
||||||
|
|
||||||
if (signal.size === 1) {
|
|
||||||
drawSimpleSignal(ctx, datas);
|
|
||||||
} else {
|
|
||||||
// adwa
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {{
|
|
||||||
* kind: 'var' | 'scope',
|
|
||||||
* type: 'wire' | 'reg' | 'module',
|
|
||||||
* name: string,
|
|
||||||
* size: number,
|
|
||||||
* link: string
|
|
||||||
* }} signal
|
|
||||||
*/
|
|
||||||
function makeWaveSvg(signal) {
|
|
||||||
const mainRender = getMainRenderEl();
|
|
||||||
const height = globalSetting.displaySignalHeight;
|
|
||||||
const width = document.body.clientWidth;
|
|
||||||
const draw = SVG().addTo(mainRender).size(width, height);
|
|
||||||
const datas = signalValues[signal.link];
|
|
||||||
|
|
||||||
if (signal.size === 1) {
|
|
||||||
drawSimpleSignalSvg(draw, datas);
|
|
||||||
} else {
|
|
||||||
// adwa
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {Svg} ctx
|
|
||||||
* @param {Array<{
|
|
||||||
* time: BigInt,
|
|
||||||
* cmd: number,
|
|
||||||
* value?: BigInt,
|
|
||||||
* mask?: BigInt
|
|
||||||
* }>} signals
|
|
||||||
*/
|
|
||||||
function drawSimpleSignalSvg(ctx, signals) {
|
|
||||||
let lastData = null;
|
|
||||||
let lastX = 300;
|
|
||||||
let lastColor = '';
|
|
||||||
|
|
||||||
// ctx.lineWidth = 3;
|
|
||||||
// ctx.lineJoin = 'round';
|
|
||||||
|
|
||||||
// const drawer = new LineDrawer(ctx);
|
|
||||||
// drawer.beginPath();
|
|
||||||
for (const data of signals) {
|
|
||||||
if (lastData === null) {
|
|
||||||
lastData = data;
|
|
||||||
lastX = 300;
|
|
||||||
lastColor = getDataRenderColor(data);
|
|
||||||
let lastY = Math.max((15 - data.cmd) * 30, 0) + 10;
|
|
||||||
// drawer.moveTo(last_x, last_y);
|
|
||||||
ctx.move(lastX, lastY);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// 高阻态
|
|
||||||
const start = lastData.time;
|
|
||||||
const end = data.time;
|
|
||||||
console.log(lastData, isBlocked(lastData));
|
|
||||||
let lastY = Math.max((15 - lastData.cmd) * 30, 0) + 10;
|
|
||||||
|
|
||||||
const duration = parseInt(end - start);
|
|
||||||
const currentX = lastX + 100;
|
|
||||||
const currentColor = getDataRenderColor(data);
|
|
||||||
console.log(currentX, lastY, duration);
|
|
||||||
|
|
||||||
const line = ctx.line(lastX, lastY, currentX, lastY);
|
|
||||||
|
|
||||||
if (currentColor !== lastColor) {
|
|
||||||
ctx.stroke({ color: lastColor, linecap: 'round', width: 3 });
|
|
||||||
}
|
|
||||||
// drawer.lineTo(current_x, last_y, color);
|
|
||||||
|
|
||||||
if (lastData.cmd !== data.cmd) {
|
|
||||||
let currentY = Math.max((15 - data.cmd) * 30, 0) + 10;
|
|
||||||
const color = getDataRenderColor(data);
|
|
||||||
ctx.line(currentX, lastY, currentX, currentY);
|
|
||||||
// drawer.lineTo(current_x, current_y, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
lastData = data;
|
|
||||||
lastX = currentX;
|
|
||||||
lastColor = currentColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果 last_data 的时间不足最长时间,就用最后一个时刻的去补足
|
|
||||||
ctx.stroke({ color: lastColor, linecap: 'round', width: 3 });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getDataRenderColor(data) {
|
|
||||||
return isBlocked(data) ? 'rgb(224,108,117)' : 'rgb(10, 200, 10)';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {{
|
|
||||||
* kind: 'var' | 'scope',
|
|
||||||
* type: 'wire' | 'reg' | 'module',
|
|
||||||
* name: string,
|
|
||||||
* size: number,
|
|
||||||
* link: string
|
|
||||||
* }} signal
|
|
||||||
*/
|
|
||||||
function removeWaveCanvas(signal) {
|
|
||||||
const canvas = canvasMap.get(signal);
|
|
||||||
if (canvas instanceof HTMLCanvasElement) {
|
|
||||||
canvas.parentNode.removeChild(canvas);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {CanvasRenderingContext2D} ctx
|
|
||||||
* @param {Array<{
|
|
||||||
* time: BigInt,
|
|
||||||
* cmd: number,
|
|
||||||
* value?: BigInt,
|
|
||||||
* mask?: BigInt
|
|
||||||
* }>} signals
|
|
||||||
*/
|
|
||||||
function drawSimpleSignal(ctx, signals) {
|
|
||||||
let last_data = null;
|
|
||||||
let last_x = 300;
|
|
||||||
|
|
||||||
ctx.lineWidth = 3;
|
|
||||||
ctx.lineJoin = 'round';
|
|
||||||
const drawer = new LineDrawer(ctx);
|
|
||||||
|
|
||||||
drawer.beginPath();
|
|
||||||
for (const data of signals) {
|
|
||||||
if (last_data === null) {
|
|
||||||
last_data = data;
|
|
||||||
last_x = 300;
|
|
||||||
let last_y = Math.max((15 - last_data.cmd) * 30, 0) + 10;
|
|
||||||
drawer.moveTo(last_x, last_y);
|
|
||||||
} else {
|
|
||||||
// 高阻态
|
|
||||||
const start = last_data.time;
|
|
||||||
const end = data.time;
|
|
||||||
console.log(last_data, isBlocked(last_data));
|
|
||||||
let last_y = Math.max((15 - last_data.cmd) * 30, 0) + 10;
|
|
||||||
|
|
||||||
const duration = parseInt(end - start);
|
|
||||||
const current_x = last_x + 100;
|
|
||||||
|
|
||||||
console.log(current_x, last_y, duration);
|
|
||||||
|
|
||||||
const color = getDataRenderColor(last_data);
|
|
||||||
drawer.lineTo(current_x, last_y, color);
|
|
||||||
|
|
||||||
if (last_data.cmd !== data.cmd) {
|
|
||||||
let current_y = Math.max((15 - data.cmd) * 30, 0) + 10;
|
|
||||||
const color = getDataRenderColor(data);
|
|
||||||
drawer.lineTo(current_x, current_y, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
last_data = data;
|
|
||||||
last_x = current_x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果 last_data 的时间不足最长时间,就用最后一个时刻的去补足
|
|
||||||
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
|
|
||||||
function pluginLocalStore(desc, pstate /* , els */) {
|
function pluginLocalStore(desc, pstate /* , els */) {
|
||||||
const pstateJsonString = JSON.stringify({
|
const pstateJsonString = JSON.stringify({
|
||||||
@ -278,22 +55,7 @@ function makeWaveView(parentElement) {
|
|||||||
console.log('updater');
|
console.log('updater');
|
||||||
};
|
};
|
||||||
|
|
||||||
const cmState = createCodeMirrorState(globalLookup, container.pstate);
|
container.elo.container.addEventListener('wheel', genOnWheel(parentElement, container.pstate, globalLookup, keyBindo));
|
||||||
|
|
||||||
const cm = mountCodeMirror6(
|
|
||||||
cmState,
|
|
||||||
container.elo.waveqlPanel,
|
|
||||||
globalLookup,
|
|
||||||
container.pstate
|
|
||||||
);
|
|
||||||
|
|
||||||
cm.view.dispatch({changes: {from: 0, insert: ' '}});
|
|
||||||
cm.view.dispatch({changes: {from: 0, to: 1, insert: ''}});
|
|
||||||
|
|
||||||
container.elo.container.addEventListener('keydown', genKeyHandler.genKeyHandler(parentElement, container.pstate, globalLookup, cm, keyBindo));
|
|
||||||
container.elo.container.addEventListener('wheel', genOnWheel(parentElement, container.pstate, globalLookup, cm, keyBindo));
|
|
||||||
// console.log(cm);
|
|
||||||
// cm.view.focus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -309,18 +71,20 @@ function makeWaveView(parentElement) {
|
|||||||
function toggleRender(signal) {
|
function toggleRender(signal) {
|
||||||
if (globalLookup.currentWires.has(signal)) {
|
if (globalLookup.currentWires.has(signal)) {
|
||||||
globalLookup.currentWires.delete(signal);
|
globalLookup.currentWires.delete(signal);
|
||||||
|
delete globalLookup.currentSignalValues[signal.link];
|
||||||
globalLookup.render();
|
globalLookup.render();
|
||||||
} else {
|
} else {
|
||||||
globalLookup.currentWires.add(signal);
|
globalLookup.currentWires.add(signal);
|
||||||
|
const signalItem = globalLookup.chango[signal.link];
|
||||||
|
const { wave } = signalItem;
|
||||||
|
const time = globalLookup.currentTime;
|
||||||
|
globalLookup.currentSignalValues[signal.link] = findCurrentSignalValue(wave, time);
|
||||||
globalLookup.render();
|
globalLookup.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getMainRenderEl,
|
getMainRenderEl,
|
||||||
makeWaveCanvas,
|
|
||||||
makeWaveSvg,
|
|
||||||
removeWaveCanvas,
|
|
||||||
makeWaveView,
|
makeWaveView,
|
||||||
toggleRender
|
toggleRender
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable no-undef */
|
/* eslint-disable no-undef */
|
||||||
|
|
||||||
import { Stream } from "stream";
|
import { Stream } from "stream";
|
||||||
|
import { globalLookup } from "./global";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -110,34 +111,100 @@ function makeSearchResultItem(searchString, module, searchScope, caseSensitivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
let htmlString = '';
|
let htmlString = '';
|
||||||
let depString = '';
|
|
||||||
let currentCounts = 0;
|
let currentCounts = 0;
|
||||||
for (let i = deps.length - 1; i >= 0; -- i) {
|
for (let i = deps.length - 1; i >= 0; -- i) {
|
||||||
const mod = deps[i];
|
const mod = deps[i];
|
||||||
// const displayName = mod.name.length > 6 ? mod.name.substring(0, 6) + '...' : mod.name;
|
// const displayName = mod.name.length > 6 ? mod.name.substring(0, 6) + '...' : mod.name;
|
||||||
const iconClass = makeIconClass(mod);
|
const iconClass = makeIconClass(mod);
|
||||||
const iconText = `<span class="iconfont ${iconClass}"></span> ${mod.name}`;
|
const iconText = `<span class="iconfont ${iconClass}"></span> ${mod.name}`;
|
||||||
|
|
||||||
depString += iconText;
|
|
||||||
htmlString += iconText;
|
htmlString += iconText;
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
depString += '<br>';
|
|
||||||
htmlString += '<div class="dep-arrow"></div>';
|
htmlString += '<div class="dep-arrow"></div>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
htmlString,
|
htmlString,
|
||||||
module,
|
module
|
||||||
depString
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {BigInt} value
|
||||||
|
* @param {BigInt} mask
|
||||||
|
* @returns {number | string}
|
||||||
|
*/
|
||||||
|
function getWireValueCaption(value, mask) {
|
||||||
|
if (!mask) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
// mask 不为空,代表存在问题
|
||||||
|
if (value) {
|
||||||
|
return '?';
|
||||||
|
} else {
|
||||||
|
return 'x';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateWireCurrentValue() {
|
||||||
|
const chango = globalLookup.chango;
|
||||||
|
const time = globalLookup.currentTime;
|
||||||
|
const currentSignalValues = globalLookup.currentSignalValues;
|
||||||
|
|
||||||
|
for (const signal of globalLookup.currentWires) {
|
||||||
|
const signalItem = chango[signal.link];
|
||||||
|
const { wave } = signalItem;
|
||||||
|
if (wave === undefined || wave.length === 0) {
|
||||||
|
currentSignalValues[signal.link] = 'x';
|
||||||
|
} else if (wave.length === 1) {
|
||||||
|
currentSignalValues[signal.link] = getWireValueCaption(wave[0][1], wave[0][2]);
|
||||||
|
} else {
|
||||||
|
currentSignalValues[signal.link] = findCurrentSignalValue(wave, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log(signal.name, currentSignalValues[signal.link]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Array<Array<string | number>>} wave
|
||||||
|
* @param {number} time
|
||||||
|
*/
|
||||||
|
function findCurrentSignalValue(wave, time) {
|
||||||
|
const times = wave.map(p => p[0]);
|
||||||
|
|
||||||
|
// 二分查找,并将结果存入 i
|
||||||
|
let i = 0, j = wave.length - 1;
|
||||||
|
while (i < j) {
|
||||||
|
if (times[i] === time) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (times[j] === time) {
|
||||||
|
i = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j - i === 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const mid = (i + j) >> 1;
|
||||||
|
if (times[mid] > time) {
|
||||||
|
j = mid;
|
||||||
|
} else {
|
||||||
|
i = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = getWireValueCaption(wave[i][1], wave[i][2]);
|
||||||
|
console.log(wave[i][1], wave[i][2]);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} timescale
|
* @param {string} timescale
|
||||||
@ -263,5 +330,7 @@ export {
|
|||||||
parseTimescale,
|
parseTimescale,
|
||||||
numberOrString,
|
numberOrString,
|
||||||
gcd,
|
gcd,
|
||||||
normaliseUsingGCD
|
findCurrentSignalValue,
|
||||||
|
normaliseUsingGCD,
|
||||||
|
updateWireCurrentValue
|
||||||
};
|
};
|
@ -14,7 +14,9 @@ const setTime = (pstate, str) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const mouseMoveHandler = (cursor, content, pstate /* , render */) => {
|
const mouseMoveHandler = (cursor, content, pstate /* , render */) => {
|
||||||
|
// 这是上面展示当前 time 的圆角矩形框框的宽度
|
||||||
const xmargin = 160;
|
const xmargin = 160;
|
||||||
|
// 这是上面展示当前 time 的圆角矩形内的字体大小
|
||||||
const fontHeight = 20;
|
const fontHeight = 20;
|
||||||
const fontWidth = fontHeight / 2;
|
const fontWidth = fontHeight / 2;
|
||||||
const handler = event => {
|
const handler = event => {
|
||||||
@ -22,6 +24,7 @@ const mouseMoveHandler = (cursor, content, pstate /* , render */) => {
|
|||||||
cursor.style.left = (x - xmargin) + 'px';
|
cursor.style.left = (x - xmargin) + 'px';
|
||||||
cursor.innerHTML = renderCursor({ xmargin, fontWidth, fontHeight }, pstate);
|
cursor.innerHTML = renderCursor({ xmargin, fontWidth, fontHeight }, pstate);
|
||||||
};
|
};
|
||||||
|
// 添加初始鼠标位置
|
||||||
handler({ clientX: pstate.width / 2 });
|
handler({ clientX: pstate.width / 2 });
|
||||||
content.addEventListener('mousemove', handler);
|
content.addEventListener('mousemove', handler);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const genOnWheel = (element, pstate, deso, cm, keyBindo, plugins) =>
|
const genOnWheel = (element, pstate, deso, keyBindo, plugins) =>
|
||||||
event => {
|
event => {
|
||||||
const {deltaY} = event;
|
const {deltaY} = event;
|
||||||
if (event.ctrlKey) {
|
if (event.ctrlKey) {
|
||||||
|
@ -6,7 +6,7 @@ const cColors = new Float32Array([
|
|||||||
|
|
||||||
0.2, 0.847, 0.1, 1, // 2: strong 0
|
0.2, 0.847, 0.1, 1, // 2: strong 0
|
||||||
0.2, 0.847, 0.1, 1, // 3: strong 1
|
0.2, 0.847, 0.1, 1, // 3: strong 1
|
||||||
1, 0, 0, 1, // 4: (x X) strong unknown
|
0.9, 0.2, 0.2, 1, // 4: (x X) strong unknown
|
||||||
|
|
||||||
.5, 1, 1, 1, // 5: vec
|
.5, 1, 1, 1, // 5: vec
|
||||||
1, 1, 0, 1, // 6: yellow
|
1, 1, 0, 1, // 6: yellow
|
||||||
@ -289,27 +289,25 @@ class WebGL2WaveRender {
|
|||||||
const vertices = [];
|
const vertices = [];
|
||||||
const ilen = wave.length;
|
const ilen = wave.length;
|
||||||
for (let i = 0; i < ilen; i++) {
|
for (let i = 0; i < ilen; i++) {
|
||||||
const [tim, val, msk] = wave[i];
|
const [t1, val, msk] = wave[i];
|
||||||
const tt = (i === (ilen - 1)) ? time : wave[i + 1][0];
|
const t2 = (i === (ilen - 1)) ? time : wave[i + 1][0];
|
||||||
|
|
||||||
if (val) {
|
if (msk) {
|
||||||
if (msk) {
|
vertices.push(...brick[2](2, 2, t1, t2, 4, 4)); // x,z?
|
||||||
vertices.push(...brick[2](2, 2, tim, tt, 4, 4)); // x,z?
|
|
||||||
} else {
|
|
||||||
vertices.push(
|
|
||||||
tim, 0, 0,
|
|
||||||
tt, 0, 0, tt, 0, 5, tt, 4, 5,
|
|
||||||
tim, 6, 5, tim, 0, 5, tim, 3, 5,
|
|
||||||
tt, 1, 5, tt, 0, 5
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (msk) {
|
vertices.push(
|
||||||
vertices.push(...brick[2](2, 2, tim, tt, 4, 4)); // x
|
t1, 0, 0,
|
||||||
} else {
|
t2, 0, 0,
|
||||||
vertices.push(tim, 6, 2, tt, 4, 2);
|
t2, 0, 5,
|
||||||
}
|
t2, 4, 5,
|
||||||
|
t1, 6, 5,
|
||||||
|
t1, 0, 5,
|
||||||
|
t1, 3, 5,
|
||||||
|
t2, 1, 5,
|
||||||
|
t2, 0, 5
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Uint32Array(vertices);
|
return new Uint32Array(vertices);
|
||||||
|
@ -8,6 +8,8 @@ const genResizeHandler = pstate =>
|
|||||||
pstate.width = width;
|
pstate.width = width;
|
||||||
pstate.height = height;
|
pstate.height = height;
|
||||||
|
|
||||||
|
console.log('time', time);
|
||||||
|
|
||||||
// Y
|
// Y
|
||||||
const yOffsetMax = (numLanes + 2) * 2 * yStep;
|
const yOffsetMax = (numLanes + 2) * 2 * yStep;
|
||||||
if (yOffsetMax < 0) {
|
if (yOffsetMax < 0) {
|
||||||
@ -16,11 +18,13 @@ const genResizeHandler = pstate =>
|
|||||||
yOffset = yOffsetMax;
|
yOffset = yOffsetMax;
|
||||||
}
|
}
|
||||||
pstate.yOffset = yOffset;
|
pstate.yOffset = yOffset;
|
||||||
console.log('resize handler', pstate);
|
// console.log('resize handler', pstate);
|
||||||
// X
|
// X
|
||||||
const xScaleMin = pstate.xScaleMin = (width - sidebarWidth) / time;
|
// const xScaleMin = pstate.xScaleMin = (width - sidebarWidth) / time;
|
||||||
|
const xScaleMin = pstate.xScaleMin = 0.001;
|
||||||
|
console.log(width, sidebarWidth);
|
||||||
|
console.log('xScaleMin', xScaleMin);
|
||||||
pstate.xScale = (xScale < xScaleMin) ? xScaleMin : xScale;
|
pstate.xScale = (xScale < xScaleMin) ? xScaleMin : xScale;
|
||||||
pstate.xScaleMin = 0.001;
|
|
||||||
xOffsetUpdate(pstate, xOffset);
|
xOffsetUpdate(pstate, xOffset);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,31 +3,33 @@
|
|||||||
const format = require('./format.js');
|
const format = require('./format.js');
|
||||||
|
|
||||||
const getLabel = (lane) => {
|
const getLabel = (lane) => {
|
||||||
if (typeof lane !== 'object') {
|
if (typeof lane !== 'object') {
|
||||||
lane = {};
|
lane = {};
|
||||||
}
|
|
||||||
const fmt = lane.format || '%h';
|
|
||||||
const width = Number(lane.width || 1);
|
|
||||||
const formatter = format(fmt, width);
|
|
||||||
|
|
||||||
return (vPre, mPre, x, w) => {
|
|
||||||
|
|
||||||
if (mPre) {
|
|
||||||
if (vPre) {
|
|
||||||
return ['text', {x, class: 'zxviolet'}, '?'];
|
|
||||||
} else {
|
|
||||||
return ['text', {x, class: 'xred'}, 'x'];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const fmt = lane.format || '%h';
|
||||||
|
const width = Number(lane.width || 1);
|
||||||
|
const formatter = format(fmt, width);
|
||||||
|
|
||||||
const pos = (w / 8) |0;
|
return (value, mask, x, w) => {
|
||||||
|
console.log(value, mask, x, w);
|
||||||
|
|
||||||
vPre = BigInt(vPre);
|
if (mask) {
|
||||||
|
if (value) {
|
||||||
|
return ['text', { x, class: 'unknown' }, '?'];
|
||||||
|
} else {
|
||||||
|
return ['text', { x, class: 'high-impedance' }, 'x'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const txtShort = formatter(vPre, pos, width);
|
|
||||||
|
|
||||||
return ['text', {x}, txtShort];
|
const pos = (w / 8) | 0;
|
||||||
};
|
|
||||||
|
value = BigInt(value);
|
||||||
|
|
||||||
|
const txtShort = formatter(value, pos, width);
|
||||||
|
|
||||||
|
return ['text', { x, class: 'common' }, txtShort];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = getLabel;
|
module.exports = getLabel;
|
||||||
|
@ -11,12 +11,12 @@ const yScroll = delta => (pstate, cm) => {
|
|||||||
|
|
||||||
const pluso = {
|
const pluso = {
|
||||||
desc: 'Zoom in time',
|
desc: 'Zoom in time',
|
||||||
fn: pstate => xScaleUpdate(pstate, 3 / 2 * pstate.xScale)
|
fn: pstate => xScaleUpdate(pstate, 10 / 9 * pstate.xScale)
|
||||||
};
|
};
|
||||||
|
|
||||||
const minuso = {
|
const minuso = {
|
||||||
desc: 'Zoom out time',
|
desc: 'Zoom out time',
|
||||||
fn: pstate => xScaleUpdate(pstate, 2 / 3 * pstate.xScale)
|
fn: pstate => xScaleUpdate(pstate, 9 / 10 * pstate.xScale)
|
||||||
};
|
};
|
||||||
|
|
||||||
const fullo = {
|
const fullo = {
|
||||||
@ -27,11 +27,11 @@ const fullo = {
|
|||||||
const scroll = {
|
const scroll = {
|
||||||
left: {
|
left: {
|
||||||
desc: 'Scroll into the past',
|
desc: 'Scroll into the past',
|
||||||
fn: pstate => xOffsetUpdate(pstate, pstate.xOffset + .2 * pstate.width)
|
fn: pstate => xOffsetUpdate(pstate, pstate.xOffset + pstate.time)
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
desc: 'Scroll into the future',
|
desc: 'Scroll into the future',
|
||||||
fn: pstate => xOffsetUpdate(pstate, pstate.xOffset - .2 * pstate.width)
|
fn: pstate => xOffsetUpdate(pstate, pstate.xOffset - pstate.time)
|
||||||
},
|
},
|
||||||
up: {
|
up: {
|
||||||
desc: 'scroll up',
|
desc: 'scroll up',
|
||||||
|
@ -4,11 +4,14 @@ const genSVG = require('onml/gen-svg.js');
|
|||||||
const stringify = require('onml/stringify.js');
|
const stringify = require('onml/stringify.js');
|
||||||
const formatTime = require('./format-time.js');
|
const formatTime = require('./format-time.js');
|
||||||
|
|
||||||
|
const { globalLookup } = require('../global');
|
||||||
|
|
||||||
const renderCursor = (cfg, pstate) => {
|
const renderCursor = (cfg, pstate) => {
|
||||||
const { xmargin, fontWidth, fontHeight } = cfg;
|
const { xmargin, fontWidth, fontHeight } = cfg;
|
||||||
const { height, xScale, xOffset, tgcd, timescale, xCursor } = pstate;
|
const { height, xScale, xOffset, tgcd, timescale, xCursor } = pstate;
|
||||||
|
|
||||||
const xx = Math.round((xCursor - xOffset) / xScale) * tgcd;
|
const xx = Math.round((xCursor - xOffset) / xScale) * tgcd;
|
||||||
|
globalLookup.currentTime = xx;
|
||||||
const label = formatTime(xx, timescale);
|
const label = formatTime(xx, timescale);
|
||||||
const lWidth = (label.length + 1) * fontWidth;
|
const lWidth = (label.length + 1) * fontWidth;
|
||||||
|
|
||||||
|
@ -88,16 +88,21 @@ function* renderValues(desc, pstate) {
|
|||||||
const labeler = getLabel(lane);
|
const labeler = getLabel(lane);
|
||||||
for (let j = 1; j <= jlen; j++) {
|
for (let j = 1; j <= jlen; j++) {
|
||||||
const mark = wave[j];
|
const mark = wave[j];
|
||||||
|
|
||||||
const [tCur, vCur, mCur] = (mark || [desc.time, 0, 0]);
|
const [tCur, vCur, mCur] = (mark || [desc.time, 0, 0]);
|
||||||
const xCur = getX(pstate, tCur);
|
const xCur = getX(pstate, tCur);
|
||||||
if (vPre || mPre) {
|
console.log(mark, vPre, mPre, vCur, mCur);
|
||||||
|
|
||||||
|
if (vPre !== undefined || mPre !== undefined) {
|
||||||
if (xPre > width && xCur > width) { // both time stamps to the right
|
if (xPre > width && xCur > width) { // both time stamps to the right
|
||||||
break perLane;
|
break perLane;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!((xPre < sidebarWidth) && (xCur < sidebarWidth))) { // both time stamps to the left
|
if (!((xPre < sidebarWidth) && (xCur < sidebarWidth))) { // both time stamps to the left
|
||||||
const xPreNorm = ((xPre > sidebarWidth) ? xPre : sidebarWidth) | 0;
|
const xPreNorm = ((xPre > sidebarWidth) ? xPre : sidebarWidth) | 0;
|
||||||
const xCurNorm = ((xCur < width) ? xCur : width) | 0;
|
const xCurNorm = ((xCur < width) ? xCur : width) | 0;
|
||||||
const w = xCurNorm - xPreNorm;
|
const w = xCurNorm - xPreNorm;
|
||||||
|
// 宽度太小不画了
|
||||||
if (w > 8) {
|
if (w > 8) {
|
||||||
const x = Math.round((xPreNorm + xCurNorm) / 2);
|
const x = Math.round((xPreNorm + xCurNorm) / 2);
|
||||||
mLane.push(labeler(vPre, mPre, x, w));
|
mLane.push(labeler(vPre, mPre, x, w));
|
||||||
@ -106,7 +111,9 @@ function* renderValues(desc, pstate) {
|
|||||||
}
|
}
|
||||||
xPre = xCur;
|
xPre = xCur;
|
||||||
vPre = vCur;
|
vPre = vCur;
|
||||||
|
console.log(mPre, mCur);
|
||||||
mPre = mCur;
|
mPre = mCur;
|
||||||
|
console.log(mPre, mCur);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ml.push(mLane);
|
ml.push(mLane);
|
||||||
|
@ -1,202 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const get = require('lodash.get');
|
|
||||||
|
|
||||||
const diz = (cols, wires, path, rowIdx) => {
|
|
||||||
if (cols[0] !== 'DIZ') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const levelo = get(wires, path, false);
|
|
||||||
const arg1 = cols[1]; // pipeline stages
|
|
||||||
|
|
||||||
// find all potential candidates
|
|
||||||
const othero0 = Object.keys(levelo).reduce((res, name) => {
|
|
||||||
const m = name.match(arg1);
|
|
||||||
if (m) {
|
|
||||||
const {id, pc, go} = m.groups;
|
|
||||||
const stage = res[id] = (res[id] || {});
|
|
||||||
const desc = {name, ref: levelo[name]};
|
|
||||||
if (pc) {
|
|
||||||
stage[pc] = desc;
|
|
||||||
} else
|
|
||||||
if (go) {
|
|
||||||
stage[go] = desc;
|
|
||||||
} else {
|
|
||||||
console.log(desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
// filter out singles
|
|
||||||
const othero = Object.keys(othero0).reduce((res, name) => {
|
|
||||||
const val = othero0[name];
|
|
||||||
if (val.pc && val.go) {
|
|
||||||
res[name] = val;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
return {kind: 'DIZ', idx: rowIdx, othero, clock: {name: 'clock', ref: levelo.clock}};
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.parser = wires => str => {
|
|
||||||
const arr = str.split('\n');
|
|
||||||
const path = [];
|
|
||||||
const labelo = {};
|
|
||||||
let nRow;
|
|
||||||
let mat;
|
|
||||||
|
|
||||||
const res = arr.map((row, rowIdx) => {
|
|
||||||
row = row.trim();
|
|
||||||
|
|
||||||
// Section with Parentheses
|
|
||||||
|
|
||||||
if (row[0] === '(') {
|
|
||||||
const cols = row.slice(1).split(/\s+/);
|
|
||||||
const res = diz(cols, wires, path, rowIdx); // || other commands
|
|
||||||
if (res) {
|
|
||||||
nRow = res;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row[0] === ')') {
|
|
||||||
if (nRow !== undefined) {
|
|
||||||
nRow.len = rowIdx - nRow.idx + 1;
|
|
||||||
nRow = undefined;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const rowo = {};
|
|
||||||
const cols = row.split(/\s+/);
|
|
||||||
cols.map(col => {
|
|
||||||
if (col === '...') { path.pop(); path.pop(); return; }
|
|
||||||
if (col === '..') { path.pop(); return; }
|
|
||||||
if (col === '.') { return; }
|
|
||||||
if (col === '/') { path.length = 0; return; }
|
|
||||||
|
|
||||||
mat = col.match(/^:(\S+)$/); if (mat) {
|
|
||||||
labelo[mat[1]] = rowo;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mat = col.match(/^(\{)([^}]+)(\})$/); if (mat) {
|
|
||||||
const a = mat[2];
|
|
||||||
const b = a.split(',');
|
|
||||||
rowo.kind = 'brace';
|
|
||||||
rowo.body = b.reduce((res, e) => {
|
|
||||||
const ee = e.split(':');
|
|
||||||
if (ee.length === 2) {
|
|
||||||
const key = ee[0];
|
|
||||||
const val = labelo[ee[1]] || Number(ee[1]);
|
|
||||||
res[key] = val;
|
|
||||||
} else
|
|
||||||
if (ee.length === 1) {
|
|
||||||
res[ee[0]] = labelo[ee[0]] || {};
|
|
||||||
} else {
|
|
||||||
console.error(ee);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}, {});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mat = col.match(/^%([<>^])?([+-])?([su])?([bodhHac])$/); if (mat) {
|
|
||||||
rowo.format = {
|
|
||||||
align: mat[1],
|
|
||||||
plus: mat[2],
|
|
||||||
sign: mat[3],
|
|
||||||
radix: mat[4]
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newPath = path.concat(col);
|
|
||||||
const ref = get(wires, newPath, false);
|
|
||||||
|
|
||||||
if (typeof ref === 'string') {
|
|
||||||
rowo.name = col;
|
|
||||||
rowo.ref = ref;
|
|
||||||
} else
|
|
||||||
if (typeof ref === 'object') {
|
|
||||||
path.push(col);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return rowo;
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.cmMode = function(CodeMirror, desc) {
|
|
||||||
const { wires } = desc;
|
|
||||||
CodeMirror.defineMode('waveql', function() {
|
|
||||||
return {
|
|
||||||
startState: function() {
|
|
||||||
return {path: []};
|
|
||||||
},
|
|
||||||
token: function (stream, stt) {
|
|
||||||
// const line = stream.lineOracle.line;
|
|
||||||
let mat;
|
|
||||||
|
|
||||||
if (stream.eatSpace()) { return null; }
|
|
||||||
|
|
||||||
mat = stream.match(/^\.\.\.(\s+|$)/); if (mat) { stt.path.pop(); stt.path.pop(); return 'punct'; }
|
|
||||||
mat = stream.match(/^\.\.(\s+|$)/); if (mat) { stt.path.pop(); return 'punct'; }
|
|
||||||
mat = stream.match(/^\.(\s+|$)/); if (mat) { return 'punct'; }
|
|
||||||
mat = stream.match(/^\/(\s+|$)/); if (mat) { stt.path.length = 0; return 'punct'; }
|
|
||||||
|
|
||||||
mat = stream.match(/^:(\S+)(\s+|$)/); if (mat) {
|
|
||||||
return 'label';
|
|
||||||
}
|
|
||||||
|
|
||||||
mat = stream.match(/^\{[^}]+\}(\s+|$)/); if (mat) {
|
|
||||||
return 'mark';
|
|
||||||
}
|
|
||||||
|
|
||||||
mat = stream.match(/^%([<>^])?([+-])?([su])?([bodhHac])(\s+|$)/); if (mat) {
|
|
||||||
return 'format';
|
|
||||||
}
|
|
||||||
|
|
||||||
mat = stream.match(/^(\S+)(\s+|$)/); if (mat) {
|
|
||||||
const sigName = mat[1];
|
|
||||||
const newPath = stt.path.concat(sigName);
|
|
||||||
const ref = get(wires, newPath, false);
|
|
||||||
if (typeof ref === 'string') {
|
|
||||||
return 'signal';
|
|
||||||
}
|
|
||||||
if (typeof ref === 'object') {
|
|
||||||
stt.path = newPath;
|
|
||||||
return 'path';
|
|
||||||
}
|
|
||||||
return 'comment';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
CodeMirror.defineMIME('text/x-waveql', 'waveql');
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.cmHint = (CodeMirror, desc) => {
|
|
||||||
const { wires } = desc;
|
|
||||||
return async (cm /*, options */) => {
|
|
||||||
const cursor = cm.getCursor();
|
|
||||||
const token = cm.getTokenAt(cursor);
|
|
||||||
const line = cm.getLine(cursor.line);
|
|
||||||
let start = cursor.ch;
|
|
||||||
let end = cursor.ch;
|
|
||||||
while (start && /\w/.test(line.charAt(start - 1))) --start;
|
|
||||||
while (end < line.length && /\w/.test(line.charAt(end))) ++end;
|
|
||||||
const cur = token.string.trim();
|
|
||||||
const list = get(wires, token.state.path, {});
|
|
||||||
const alls = ['/', '..'].concat(Object.keys(list));
|
|
||||||
const hints = alls.filter(e => e.match(cur));
|
|
||||||
return {
|
|
||||||
list: hints,
|
|
||||||
from: CodeMirror.Pos(cursor.line, start),
|
|
||||||
to: CodeMirror.Pos(cursor.line, end)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,20 +1,26 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const xOffsetUpdate = (pstate, xOffsetNext) => {
|
const xOffsetUpdate = (pstate, nextOffsetX) => {
|
||||||
let {width, xOffset, xScale, time, sidebarWidth} = pstate;
|
const { width, xOffset, xScale, time, sidebarWidth } = pstate;
|
||||||
|
|
||||||
const xOffsetMax = sidebarWidth; // maximum offset
|
// console.log('input offset', nextOffsetX);
|
||||||
xOffsetNext = (xOffsetNext > xOffsetMax) ? xOffsetMax : xOffsetNext;
|
// console.log('xScale', xScale);
|
||||||
|
const maxOffsetX = width - xScale * time + 2000; // maximum offset
|
||||||
|
nextOffsetX = Math.min(nextOffsetX, maxOffsetX);
|
||||||
|
|
||||||
const xOffsetMin = width - xScale * time; // minimum offset
|
const minOffsetX = 0; // minimum offset
|
||||||
xOffsetNext = (xOffsetNext < xOffsetMin) ? xOffsetMin : xOffsetNext;
|
nextOffsetX = Math.max(nextOffsetX, minOffsetX);
|
||||||
|
|
||||||
if (xOffsetNext === xOffset) {
|
// console.log('max offset', maxOffsetX);
|
||||||
return false; // exit without scroll
|
// console.log('min offset', minOffsetX);
|
||||||
}
|
// console.log('next offset', nextOffsetX);
|
||||||
|
|
||||||
pstate.xOffset = xOffsetNext;
|
if (nextOffsetX === xOffset) {
|
||||||
return true;
|
return false; // exit without scroll
|
||||||
|
}
|
||||||
|
|
||||||
|
pstate.xOffset = nextOffsetX;
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = xOffsetUpdate;
|
module.exports = xOffsetUpdate;
|
||||||
|
@ -9,8 +9,7 @@ const xScaleUpdate = (pstate, xScaleNext) => {
|
|||||||
|
|
||||||
xScaleNext = (xScaleNext < xScaleMin) ? xScaleMin : xScaleNext;
|
xScaleNext = (xScaleNext < xScaleMin) ? xScaleMin : xScaleNext;
|
||||||
|
|
||||||
console.log('pstate', pstate);
|
// console.log('scale next', xScaleNext);
|
||||||
console.log('scale next', xScaleNext);
|
|
||||||
|
|
||||||
if (xScaleNext === xScale) {
|
if (xScaleNext === xScale) {
|
||||||
return false; // exit without scale change
|
return false; // exit without scale change
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"signal": "Signals",
|
"signal": "Signals",
|
||||||
"search-signal": "Search Signal",
|
"search-signal": "Search Signal",
|
||||||
"language-setting": "Language",
|
"language-setting": "Language",
|
||||||
|
"wheel-zoom-ratio": "Wheel Zoom Level",
|
||||||
|
|
||||||
"search-setting": "Search",
|
"search-setting": "Search",
|
||||||
"search-case-sensitivity": "Case Sensitivity",
|
"search-case-sensitivity": "Case Sensitivity",
|
||||||
@ -11,6 +12,7 @@
|
|||||||
"search-display-parent-only": "Display Parent Module Only",
|
"search-display-parent-only": "Display Parent Module Only",
|
||||||
"search-nothing": "Find Nothing",
|
"search-nothing": "Find Nothing",
|
||||||
|
|
||||||
|
|
||||||
"signal-only": "Signal Only",
|
"signal-only": "Signal Only",
|
||||||
"module-only": "Module Only",
|
"module-only": "Module Only",
|
||||||
"signal-module": "Signal + Module",
|
"signal-module": "Signal + Module",
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"signal": "信号",
|
"signal": "信号",
|
||||||
"search-signal": "搜索信号",
|
"search-signal": "搜索信号",
|
||||||
"language-setting": "语言",
|
"language-setting": "语言",
|
||||||
|
"wheel-zoom-ratio": "滚轮缩放倍率",
|
||||||
|
|
||||||
"search-setting": "搜索",
|
"search-setting": "搜索",
|
||||||
"search-case-sensitivity": "区分大小写",
|
"search-case-sensitivity": "区分大小写",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user