实现展示信号基本信息
This commit is contained in:
parent
b142e5d906
commit
6342ebfdc7
@ -1,6 +1,6 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 4797805 */
|
font-family: "iconfont"; /* Project id 4797805 */
|
||||||
src: url('iconfont.woff2?t=1735470843861') format('woff2');
|
src: url('iconfont.woff2?t=1735991360293') format('woff2');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@ -11,6 +11,22 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-link:before {
|
||||||
|
content: "\e6fa";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-Listinterface:before {
|
||||||
|
content: "\e66b";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-info-port:before {
|
||||||
|
content: "\f2e1";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-sanjiao_fill-:before {
|
||||||
|
content: "\e6a0";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-memory-chip:before {
|
.icon-memory-chip:before {
|
||||||
content: "\e600";
|
content: "\e600";
|
||||||
}
|
}
|
||||||
@ -243,3 +259,7 @@
|
|||||||
content: "\e693";
|
content: "\e693";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-info-module:before {
|
||||||
|
content: "\f2e2";
|
||||||
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
81
src/api/definition.js
Normal file
81
src/api/definition.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import { globalLookup } from "@/hook/global";
|
||||||
|
import { pinkLog } from "@/hook/utils";
|
||||||
|
import { mode } from ".";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} definition
|
||||||
|
*/
|
||||||
|
export async function gotoDefinition(definition) {
|
||||||
|
const defs = processDefinition(definition);
|
||||||
|
if (mode === 'debug') {
|
||||||
|
const res = await axios.post('http://localhost:3000/netlist/goto-definition', { defs });
|
||||||
|
} else {
|
||||||
|
vscode.postMessage({
|
||||||
|
command: 'save-as-svg',
|
||||||
|
data: { svgBuffer, moduleName }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @typedef FileRange
|
||||||
|
* @property {string} path
|
||||||
|
* @property {import("@/hook/jsdoc").Range} [range]
|
||||||
|
*
|
||||||
|
* @param {string | undefined} definition
|
||||||
|
* @returns {FileRange[]}
|
||||||
|
*/
|
||||||
|
function processDefinition(definition) {
|
||||||
|
if (typeof definition !== 'string') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (definition.includes('|')) {
|
||||||
|
const defs = [];
|
||||||
|
for (const def of definition.split('|')) {
|
||||||
|
defs.push(...processDefinition(def));
|
||||||
|
}
|
||||||
|
return defs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (definition.includes(':')) {
|
||||||
|
const [path, rangeString] = definition.split(':');
|
||||||
|
const [startString, endString] = rangeString.split('-');
|
||||||
|
const [startLine, startCharacter] = startString.split('.');
|
||||||
|
const [endLine, endCharacter] = endString.split('.');
|
||||||
|
const range = {
|
||||||
|
start: {
|
||||||
|
line: parseRangeInt(startLine),
|
||||||
|
character: parseRangeInt(startCharacter)
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
line: parseRangeInt(endLine),
|
||||||
|
character: parseRangeInt(endCharacter)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return [
|
||||||
|
{ path, range }
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
path: definition,
|
||||||
|
range: undefined
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseRangeInt(s) {
|
||||||
|
const i = parseInt(s);
|
||||||
|
if (i > 0) {
|
||||||
|
// 因为 yosys 是 one index 的,但是 vscode 内部跳转都是 zero index
|
||||||
|
return i - 1;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
@ -5,7 +5,7 @@ import { pinkLog } from "@/hook/utils";
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import pako from 'pako';
|
import pako from 'pako';
|
||||||
|
|
||||||
const mode = window.acquireVsCodeApi === undefined ? 'debug' : 'release';
|
export const mode = window.acquireVsCodeApi === undefined ? 'debug' : 'release';
|
||||||
pinkLog('digital-netlist-render mode: ' + mode);
|
pinkLog('digital-netlist-render mode: ' + mode);
|
||||||
|
|
||||||
let vscode = window.acquireVsCodeApi === undefined ? undefined : acquireVsCodeApi();
|
let vscode = window.acquireVsCodeApi === undefined ? undefined : acquireVsCodeApi();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="about-wrapper">
|
<div class="about-wrapper" :style="aboutWrapper">
|
||||||
<div class="usermanual">
|
<div class="usermanual">
|
||||||
<h2>{{ t('usermanual') }}</h2>
|
<h2>{{ t('usermanual') }}</h2>
|
||||||
<div class="usermanual-item">
|
<div class="usermanual-item">
|
||||||
@ -39,8 +39,9 @@
|
|||||||
|
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { horizontalResizer } from '../right-nav';
|
||||||
|
|
||||||
defineComponent({ name: 'dide-about' });
|
defineComponent({ name: 'dide-about' });
|
||||||
|
|
||||||
@ -48,7 +49,9 @@ function goto(url) {
|
|||||||
window.open(url, '_blank');
|
window.open(url, '_blank');
|
||||||
}
|
}
|
||||||
|
|
||||||
const platform = navigator.platform;
|
const aboutWrapper = computed(() => ({
|
||||||
|
width: horizontalResizer.width - 10 + 'px'
|
||||||
|
}));
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,24 +1,36 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="netlist-tree-view">
|
<div class="netlist-tree-view">
|
||||||
<div class="netlist-module-info">
|
<div class="netlist-module-info" :style="netlistModuleStyle">
|
||||||
<div class="netlist-signal-title">{{ t('module') }}</div>
|
<div class="netlist-signal-title">{{ t('module') }}</div>
|
||||||
<hr style="width: 100%;">
|
<hr style="width: 100%;">
|
||||||
<el-scrollbar height="86vh" style="padding-right: 7px;">
|
|
||||||
|
<el-scrollbar height="40vh" style="padding-right: 7px;height: 50%;">
|
||||||
<modules
|
<modules
|
||||||
v-for="mod of treeviewData.modules"
|
v-for="mod of treeviewData.modules"
|
||||||
:key="mod.name"
|
:key="mod.name"
|
||||||
:module="mod"
|
:module="mod"
|
||||||
></modules>
|
></modules>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
|
||||||
|
<div class="netlist-signal-title">{{ t('entity-info') }}</div>
|
||||||
|
<hr style="width: 100%;">
|
||||||
|
|
||||||
|
<el-scrollbar height="40vh" style="padding-right: 7px;height: 50%;">
|
||||||
|
<info></info>
|
||||||
|
</el-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineComponent, onMounted } from 'vue';
|
import { defineComponent, onMounted, computed } from 'vue';
|
||||||
|
|
||||||
import modules from './modules.vue';
|
import modules from './modules.vue';
|
||||||
|
import info from './info.vue';
|
||||||
|
|
||||||
import { resize, treeviewData, verticalResizer } from './tree';
|
import { resize, treeviewData, verticalResizer } from './tree';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { horizontalResizer } from '../right-nav';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
@ -31,6 +43,11 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const netlistModuleStyle = computed(() => ({
|
||||||
|
width: horizontalResizer.width - 30 + 'px'
|
||||||
|
}));
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
104
src/components/treeview/info.js
Normal file
104
src/components/treeview/info.js
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { globalLookup, globalSetting } from '@/hook/global';
|
||||||
|
import { ModuleView, Port } from '@/hook/render/yosys';
|
||||||
|
import { SkinManager } from '@/hook/skin';
|
||||||
|
import i18n from '@/i18n';
|
||||||
|
import { reactive } from 'vue';
|
||||||
|
|
||||||
|
|
||||||
|
const { t, locale } = i18n.global;
|
||||||
|
locale.value = globalSetting.language;
|
||||||
|
|
||||||
|
export const infoView = reactive({
|
||||||
|
name: undefined,
|
||||||
|
|
||||||
|
type: undefined,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {'port' | 'module'}
|
||||||
|
*/
|
||||||
|
typeId: undefined,
|
||||||
|
|
||||||
|
module: undefined,
|
||||||
|
definition: undefined,
|
||||||
|
width: undefined,
|
||||||
|
direction: undefined,
|
||||||
|
|
||||||
|
|
||||||
|
// module 渲染属性
|
||||||
|
inputCount: undefined,
|
||||||
|
outputCount: undefined,
|
||||||
|
inoutCount: undefined,
|
||||||
|
instanceCount: undefined,
|
||||||
|
cellCount: undefined,
|
||||||
|
|
||||||
|
// edge 渲染属性
|
||||||
|
from: undefined,
|
||||||
|
to: undefined,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 显示一个 port 到当前信息窗口
|
||||||
|
* @param {Port} port
|
||||||
|
*/
|
||||||
|
displayPort(port) {
|
||||||
|
this.clear();
|
||||||
|
this.name = port.name;
|
||||||
|
this.module = port.view.name;
|
||||||
|
this.type = t("common.port");
|
||||||
|
this.typeId = 'port';
|
||||||
|
|
||||||
|
this.definition = port.definition;
|
||||||
|
this.width = port.width;
|
||||||
|
this.direction = port.direction;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 显示一个 module 到当前窗口
|
||||||
|
* @param {ModuleView} module
|
||||||
|
*/
|
||||||
|
displayModule(module) {
|
||||||
|
this.clear();
|
||||||
|
this.name = module.name;
|
||||||
|
this.type = t("common.instance");
|
||||||
|
this.typeId = 'module';
|
||||||
|
this.definition = module.definition;
|
||||||
|
|
||||||
|
const portInfo = module.portInfo;
|
||||||
|
this.inputCount = portInfo.input;
|
||||||
|
this.outputCount = portInfo.output;
|
||||||
|
this.inoutCount = portInfo.inout;
|
||||||
|
|
||||||
|
const skinManager = globalLookup.skinManager;
|
||||||
|
|
||||||
|
let instanceCount = 0;
|
||||||
|
let cellCount = 0;
|
||||||
|
|
||||||
|
this.instanceCount = 0;
|
||||||
|
this.cellCount = 0;
|
||||||
|
|
||||||
|
for (const cellname of module.nameToCell.keys()) {
|
||||||
|
const cell = module.nameToCell.get(cellname);
|
||||||
|
const skin = skinManager.querySkin(cell.type);
|
||||||
|
|
||||||
|
if (skin) {
|
||||||
|
cellCount ++;
|
||||||
|
} else {
|
||||||
|
instanceCount ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.instanceCount = instanceCount;
|
||||||
|
this.cellCount = cellCount;
|
||||||
|
},
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.name = undefined;
|
||||||
|
this.type = undefined;
|
||||||
|
this.module = undefined;
|
||||||
|
this.definition = undefined;
|
||||||
|
this.direction = undefined;
|
||||||
|
this.width = undefined;
|
||||||
|
this.from = undefined;
|
||||||
|
this.to = undefined;
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
@ -1,14 +1,175 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="treeview-info">
|
||||||
|
|
||||||
|
<div class="treeview-info-blank" v-if="!globalLookup.currentSelectEntity">
|
||||||
|
{{ t('info.no-entity-select.cannot-display-view') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="infoView.typeId === 'module'"
|
||||||
|
class="info-wrapper">
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t("common.type") }}</span>
|
||||||
|
<span>
|
||||||
|
<span class="iconfont icon-info-module"></span>{{ infoView.type }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t("common.name") }}</span>
|
||||||
|
<span><code>{{ infoView.name }}</code></span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>
|
||||||
|
{{ t("common.definition") }}
|
||||||
|
</span>
|
||||||
|
<span class="definition" @click="gotoDefinition(infoView.definition)">
|
||||||
|
<span class="iconfont icon-link"></span>{{ renderDefinition(infoView.definition) }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t('common.input-number') }}</span>
|
||||||
|
<span>{{ infoView.inputCount }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t('common.output-number') }}</span>
|
||||||
|
<span>{{ infoView.outputCount }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t('common.inout-number') }}</span>
|
||||||
|
<span>{{ infoView.inoutCount }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t('common.instance-number') }}</span>
|
||||||
|
<span>{{ infoView.instanceCount }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t('common.general-cell-number') }}</span>
|
||||||
|
<span>{{ infoView.cellCount }}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="infoView.typeId === 'port'"
|
||||||
|
class="info-wrapper">
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t('common.type') }}</span>
|
||||||
|
<span>
|
||||||
|
<span class="iconfont icon-info-port"></span>{{ infoView.type }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t('common.name') }}</span>
|
||||||
|
<span><code>{{ infoView.name }}</code></span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>
|
||||||
|
{{ t('common.definition') }}
|
||||||
|
</span>
|
||||||
|
<span class="definition" @click="gotoDefinition(infoView.definition)">
|
||||||
|
<span class="iconfont icon-link"></span>{{ renderDefinition(infoView.definition) }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t('common.belong-module') }}</span>
|
||||||
|
<span><span class="iconfont icon-info-module"></span><code>{{ infoView.module }}</code></span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t('common.width') }}</span>
|
||||||
|
<span>{{ infoView.width }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="info-item-container">
|
||||||
|
<span>{{ t('common.direction') }}</span>
|
||||||
|
<span>{{ infoView.direction }}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import { infoView } from './info';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { globalLookup } from '@/hook/global';
|
||||||
|
import { gotoDefinition } from '@/api/definition';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
defineComponent({ name: 'treeview-item-info' });
|
defineComponent({ name: 'treeview-item-info' });
|
||||||
|
|
||||||
|
function renderDefinition(definition) {
|
||||||
|
if (typeof definition !== 'string') {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (definition.includes('|')) {
|
||||||
|
const filenames = [];
|
||||||
|
for (const def of definition.split('|')) {
|
||||||
|
filenames.push(renderDefinition(def));
|
||||||
|
}
|
||||||
|
return filenames.join('').split(':').at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const filename = definition.split('/').at(-1);
|
||||||
|
if (!filename) {
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
|
return filename.split(':').at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.treeview-info {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.treeview-info-blank {
|
||||||
|
font-size: .9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item-container {
|
||||||
|
display: flex;
|
||||||
|
margin: 2px;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: .8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item-container span:nth-child(1) {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item-container span:nth-child(2) {
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: 220px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-wrapper > span {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom: solid 1px var(--sidebar-item-selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-wrapper > span:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item-container .definition {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: var(--animation-3s);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item-container .iconfont {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item-container .definition:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--main-color);
|
||||||
|
transition: var(--animation-3s);
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,6 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="module">
|
<div class="module">
|
||||||
<div @click="clickItem()" class="netlist-treeview-item">
|
<div @click="clickModule()"
|
||||||
|
class="netlist-treeview-item"
|
||||||
|
:class="{'active': sameModule(module) }"
|
||||||
|
>
|
||||||
<span class="module-tag-status" @click.stop="expandManage.click">
|
<span class="module-tag-status" @click.stop="expandManage.click">
|
||||||
<div :class="expandManage.expandTagClass"></div>
|
<div :class="expandManage.expandTagClass"></div>
|
||||||
</span>
|
</span>
|
||||||
@ -17,10 +20,14 @@
|
|||||||
<div style="width: 20px;"></div>
|
<div style="width: 20px;"></div>
|
||||||
<div style="width: 100%;">
|
<div style="width: 100%;">
|
||||||
<!-- ports -->
|
<!-- ports -->
|
||||||
<div v-for="port in ports" :key="port.name" class="netlist-treeview-item">
|
<div v-for="port in ports" :key="port.name"
|
||||||
|
class="netlist-treeview-item"
|
||||||
|
:class="{'active': samePort(port)}"
|
||||||
|
@click="clickPort(port)"
|
||||||
|
>
|
||||||
<span class="module-tag-status">
|
<span class="module-tag-status">
|
||||||
</span>
|
</span>
|
||||||
<span class="iconfont icon-wave-square"></span>
|
<span class="iconfont icon-info-port"></span>
|
||||||
 {{ port.name }}
|
 {{ port.name }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -41,6 +48,7 @@
|
|||||||
import { globalLookup } from '@/hook/global';
|
import { globalLookup } from '@/hook/global';
|
||||||
import { ModuleView } from '@/hook/render/yosys';
|
import { ModuleView } from '@/hook/render/yosys';
|
||||||
import { defineComponent, reactive, computed } from 'vue';
|
import { defineComponent, reactive, computed } from 'vue';
|
||||||
|
import { infoView } from './info';
|
||||||
|
|
||||||
defineComponent({ name: 'modules' });
|
defineComponent({ name: 'modules' });
|
||||||
|
|
||||||
@ -90,8 +98,47 @@ for (const cellName of module.nameToCell.keys()) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function clickItem() {
|
function sameModule(module) {
|
||||||
|
if (!globalLookup.currentSelectEntity) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const currentView = globalLookup.currentSelectEntity.moduleView;
|
||||||
|
const data = globalLookup.currentSelectEntity.data;
|
||||||
|
return data.name === module.name && currentView.name === module.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function samePort(port) {
|
||||||
|
if (!globalLookup.currentSelectEntity) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const data = globalLookup.currentSelectEntity.data;
|
||||||
|
const currentView = globalLookup.currentSelectEntity.moduleView;
|
||||||
|
return data.name === port.name && module.name === currentView.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickPort(port) {
|
||||||
|
const portView = module.nameToPort.get(port.name);
|
||||||
|
infoView.displayPort(portView);
|
||||||
|
|
||||||
|
globalLookup.currentSelectEntity = {
|
||||||
|
data: port,
|
||||||
|
type: 'port',
|
||||||
|
moduleView: props.module
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取渲染视图,并高亮对应的渲染实体
|
||||||
|
const renderView = globalLookup.netlistRender.renderView;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickModule() {
|
||||||
|
infoView.displayModule(module);
|
||||||
|
|
||||||
|
globalLookup.currentSelectEntity = {
|
||||||
|
data: props.module,
|
||||||
|
type: 'module',
|
||||||
|
moduleView: props.module
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getExpandStatus() {
|
function getExpandStatus() {
|
||||||
@ -110,16 +157,20 @@ const expandManage = reactive({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function makeIconClass() {
|
function makeIconClass() {
|
||||||
return 'icon-memory-chip';
|
return 'icon-info-module';
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.icon-memory-chip {
|
.module .icon-info-module {
|
||||||
color: #FF7043;
|
color: #FF7043;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.module .icon-info-port {
|
||||||
|
color: var(--main-color);
|
||||||
|
}
|
||||||
|
|
||||||
.module {
|
.module {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
@ -148,6 +199,12 @@ function makeIconClass() {
|
|||||||
border-radius: .3em;
|
border-radius: .3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.netlist-treeview-item.active {
|
||||||
|
background-color: var(--sidebar-item-selected);
|
||||||
|
border-radius: .3em;
|
||||||
|
transition: var(--animation-3s);
|
||||||
|
}
|
||||||
|
|
||||||
.netlist-treeview-selected {
|
.netlist-treeview-selected {
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
background-color: var(--button-active) !important;
|
background-color: var(--button-active) !important;
|
||||||
|
@ -68,6 +68,7 @@ export const globalLookup = reactive({
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 当前选择的实体,可以是 wire,也可以是 cell
|
* @description 当前选择的实体,可以是 wire,也可以是 cell
|
||||||
|
* @type {import('./jsdoc').ICurrentSelectEntity}
|
||||||
*/
|
*/
|
||||||
currentSelectEntity: undefined,
|
currentSelectEntity: undefined,
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Module } from "./render/layout";
|
import { Module } from "./render/layout";
|
||||||
|
import { ModuleView } from "./render/yosys";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {number | string} WireId 信号ID
|
* @typedef {number | string} WireId 信号ID
|
||||||
@ -269,5 +270,25 @@ import { Module } from "./render/layout";
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef ElkMakerConfig
|
* @typedef ElkMakerConfig
|
||||||
* @param {string} [parentId]
|
* @property {string} [parentId]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef ICurrentSelectEntity
|
||||||
|
* @property {any} data 数据本体,用于匹配 id
|
||||||
|
* @property {'module' | 'port'} type 类型
|
||||||
|
* @property {ModuleView} moduleView 所在模块的数据视图
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef Position
|
||||||
|
* @property {number} line
|
||||||
|
* @property {number} charater
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef Range
|
||||||
|
* @property {Position} start
|
||||||
|
* @property {Position} end
|
||||||
*/
|
*/
|
@ -233,7 +233,6 @@ export class Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const constantWidth = Math.max(12 * 0.6 * renderString.toString().length + 10, LAYOUT_CONSTANT.CONSTANT_WIDTH);
|
const constantWidth = Math.max(12 * 0.6 * renderString.toString().length + 10, LAYOUT_CONSTANT.CONSTANT_WIDTH);
|
||||||
console.log(constantWidth);
|
|
||||||
|
|
||||||
const constantConnection = {
|
const constantConnection = {
|
||||||
id: dotConnect(id, '0'),
|
id: dotConnect(id, '0'),
|
||||||
|
@ -125,4 +125,9 @@ export class RenderViewNode {
|
|||||||
this.wireRender.render();
|
this.wireRender.render();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
findNode() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -179,6 +179,35 @@ export class ModuleView {
|
|||||||
get id() {
|
get id() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef ModuleViewPortInfo
|
||||||
|
* @property {number} input
|
||||||
|
* @property {number} output
|
||||||
|
* @property {number} inout
|
||||||
|
*
|
||||||
|
* @returns {ModuleViewPortInfo}
|
||||||
|
*/
|
||||||
|
get portInfo() {
|
||||||
|
if (this._portInfo) {
|
||||||
|
return this._portInfo;
|
||||||
|
}
|
||||||
|
this._portInfo = {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
inout: 0
|
||||||
|
};
|
||||||
|
for (const portName of this.nameToPort.keys()) {
|
||||||
|
const port = this.nameToPort.get(portName);
|
||||||
|
this._portInfo[port.direction] ++;
|
||||||
|
}
|
||||||
|
return this._portInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
get definition() {
|
||||||
|
const attributes = this.rawModule.attributes;
|
||||||
|
return definitionFromAttribute(attributes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Port {
|
export class Port {
|
||||||
@ -186,7 +215,7 @@ export class Port {
|
|||||||
* @description port 的抽象
|
* @description port 的抽象
|
||||||
* @param {ModuleView} view
|
* @param {ModuleView} view
|
||||||
* @param {string} name
|
* @param {string} name
|
||||||
* @param {YosysPort} rawPort
|
* @param {import("../jsdoc").YosysPort} rawPort
|
||||||
*/
|
*/
|
||||||
constructor(view, name, rawPort) {
|
constructor(view, name, rawPort) {
|
||||||
this.view = view;
|
this.view = view;
|
||||||
@ -198,6 +227,10 @@ export class Port {
|
|||||||
return this.rawPort.bits;
|
return this.rawPort.bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get width() {
|
||||||
|
return (this.rawPort.bits || []).length;
|
||||||
|
}
|
||||||
|
|
||||||
get direction() {
|
get direction() {
|
||||||
return this.rawPort.direction;
|
return this.rawPort.direction;
|
||||||
}
|
}
|
||||||
@ -205,6 +238,15 @@ export class Port {
|
|||||||
get id() {
|
get id() {
|
||||||
return dotConnect(this.view.id, this.name);
|
return dotConnect(this.view.id, this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get definition() {
|
||||||
|
const netname = this.view.rawModule.netnames[this.name];
|
||||||
|
if (!netname) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const attributes = netname.attributes;
|
||||||
|
return definitionFromAttribute(attributes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Cell {
|
export class Cell {
|
||||||
@ -257,6 +299,11 @@ export class Cell {
|
|||||||
get id() {
|
get id() {
|
||||||
return dotConnect(this.view.id, this.name);
|
return dotConnect(this.view.id, this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get definition() {
|
||||||
|
const attributes = this.rawCell.attributes;
|
||||||
|
return definitionFromAttribute(attributes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -326,3 +373,24 @@ export function dotConnect(...args) {
|
|||||||
const stringArgs = args.map(arg => arg.toString());
|
const stringArgs = args.map(arg => arg.toString());
|
||||||
return stringArgs.join('.');
|
return stringArgs.join('.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("../jsdoc").ModuleAttribute} attributes
|
||||||
|
*/
|
||||||
|
function definitionFromAttribute(attributes) {
|
||||||
|
if (!attributes) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const src = attributes.src;
|
||||||
|
if (!src) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (src.startsWith('/dide')) {
|
||||||
|
return src.replace('/dide', '{workspace}');
|
||||||
|
}
|
||||||
|
if (src.startsWith('/lib')) {
|
||||||
|
return src.replace('/lib', '{library}');
|
||||||
|
}
|
||||||
|
return src;
|
||||||
|
}
|
@ -44,5 +44,18 @@
|
|||||||
"setting.pulsation-speed": "سرعة تأثير النبض",
|
"setting.pulsation-speed": "سرعة تأثير النبض",
|
||||||
"toolbar.save-as-svg": "حفظ العرض الحالي كـ SVG",
|
"toolbar.save-as-svg": "حفظ العرض الحالي كـ SVG",
|
||||||
"toolbar.save-as-pdf": "حفظ العرض الحالي كـ PDF",
|
"toolbar.save-as-pdf": "حفظ العرض الحالي كـ PDF",
|
||||||
"saving": "جارٍ الحفظ"
|
"saving": "جارٍ الحفظ",
|
||||||
|
"info.no-entity-select.cannot-display-view": "لم يتم تحديد أي كيان، لا يمكن عرض عرض البيانات",
|
||||||
|
"entity-info": "معلومات الكيان",
|
||||||
|
"common.type": "النوع",
|
||||||
|
"common.name": "الاسم",
|
||||||
|
"common.definition": "تعريف",
|
||||||
|
"common.belong-module": "الوحدة التابعة",
|
||||||
|
"common.width": "عرض البت",
|
||||||
|
"common.direction": "الاتجاه",
|
||||||
|
"common.input-number": "عدد الإدخال",
|
||||||
|
"common.output-number": "عدد الإخراج",
|
||||||
|
"common.inout-number": "الكمية",
|
||||||
|
"common.instance-number": "عدد الوحدات المثبتة",
|
||||||
|
"common.general-cell-number": "عدد الأجهزة العامة"
|
||||||
}
|
}
|
@ -44,5 +44,18 @@
|
|||||||
"setting.pulsation-speed": "Pulseffektgeschwindigkeit",
|
"setting.pulsation-speed": "Pulseffektgeschwindigkeit",
|
||||||
"toolbar.save-as-svg": "Aktuelle Ansicht als SVG speichern",
|
"toolbar.save-as-svg": "Aktuelle Ansicht als SVG speichern",
|
||||||
"toolbar.save-as-pdf": "Aktuelle Ansicht als PDF speichern",
|
"toolbar.save-as-pdf": "Aktuelle Ansicht als PDF speichern",
|
||||||
"saving": "Wird gespeichert"
|
"saving": "Wird gespeichert",
|
||||||
|
"info.no-entity-select.cannot-display-view": "Keine Entität ausgewählt, Datenansicht kann nicht angezeigt werden",
|
||||||
|
"entity-info": "Entitätsinformationen",
|
||||||
|
"common.type": "Typ",
|
||||||
|
"common.name": "Name",
|
||||||
|
"common.definition": "Definition",
|
||||||
|
"common.belong-module": "Zugehöriges Modul",
|
||||||
|
"common.width": "Bitbreite",
|
||||||
|
"common.direction": "Richtung",
|
||||||
|
"common.input-number": "Eingabemenge",
|
||||||
|
"common.output-number": "Ausgabemenge",
|
||||||
|
"common.inout-number": "Menge",
|
||||||
|
"common.instance-number": "Anzahl der instanziierten Module",
|
||||||
|
"common.general-cell-number": "Anzahl der allgemeinen Geräte"
|
||||||
}
|
}
|
@ -44,5 +44,18 @@
|
|||||||
"setting.pulsation-speed": "Pulse Effect Speed",
|
"setting.pulsation-speed": "Pulse Effect Speed",
|
||||||
"toolbar.save-as-svg": "Save current view as SVG",
|
"toolbar.save-as-svg": "Save current view as SVG",
|
||||||
"toolbar.save-as-pdf": "Save current view as PDF",
|
"toolbar.save-as-pdf": "Save current view as PDF",
|
||||||
"saving": "Saving"
|
"saving": "Saving",
|
||||||
|
"info.no-entity-select.cannot-display-view": "No entity selected, unable to display data view",
|
||||||
|
"entity-info": "Entity Information",
|
||||||
|
"common.type": "Type",
|
||||||
|
"common.name": "Name",
|
||||||
|
"common.definition": "Definition",
|
||||||
|
"common.belong-module": "Associated Module",
|
||||||
|
"common.width": "Bit Width",
|
||||||
|
"common.direction": "Direction",
|
||||||
|
"common.input-number": "input quantity",
|
||||||
|
"common.output-number": "output quantity",
|
||||||
|
"common.inout-number": "Quantity",
|
||||||
|
"common.instance-number": "Number of instantiated modules",
|
||||||
|
"common.general-cell-number": "Number of general devices"
|
||||||
}
|
}
|
@ -44,5 +44,18 @@
|
|||||||
"setting.pulsation-speed": "Vitesse de l'effet de pulsation",
|
"setting.pulsation-speed": "Vitesse de l'effet de pulsation",
|
||||||
"toolbar.save-as-svg": "Enregistrer la vue actuelle au format SVG",
|
"toolbar.save-as-svg": "Enregistrer la vue actuelle au format SVG",
|
||||||
"toolbar.save-as-pdf": "Enregistrer la vue actuelle en PDF",
|
"toolbar.save-as-pdf": "Enregistrer la vue actuelle en PDF",
|
||||||
"saving": "Enregistrement en cours"
|
"saving": "Enregistrement en cours",
|
||||||
|
"info.no-entity-select.cannot-display-view": "Aucune entité sélectionnée, impossible d'afficher la vue des données",
|
||||||
|
"entity-info": "Informations sur l'entité",
|
||||||
|
"common.type": "Type",
|
||||||
|
"common.name": "Nom",
|
||||||
|
"common.definition": "Définition",
|
||||||
|
"common.belong-module": "Module associé",
|
||||||
|
"common.width": "Largeur de bit",
|
||||||
|
"common.direction": "Direction",
|
||||||
|
"common.input-number": "quantité d'entrée",
|
||||||
|
"common.output-number": "quantité de sortie",
|
||||||
|
"common.inout-number": "Quantité",
|
||||||
|
"common.instance-number": "Nombre de modules instanciés",
|
||||||
|
"common.general-cell-number": "Nombre d'appareils généraux"
|
||||||
}
|
}
|
@ -44,5 +44,18 @@
|
|||||||
"setting.pulsation-speed": "パルスエフェクト速度",
|
"setting.pulsation-speed": "パルスエフェクト速度",
|
||||||
"toolbar.save-as-svg": "現在のビューをSVGとして保存",
|
"toolbar.save-as-svg": "現在のビューをSVGとして保存",
|
||||||
"toolbar.save-as-pdf": "現在のビューをPDFとして保存",
|
"toolbar.save-as-pdf": "現在のビューをPDFとして保存",
|
||||||
"saving": "保存中"
|
"saving": "保存中",
|
||||||
|
"info.no-entity-select.cannot-display-view": "エンティティが選択されていないため、データビューを表示できません",
|
||||||
|
"entity-info": "エンティティ情報",
|
||||||
|
"common.type": "タイプ",
|
||||||
|
"common.name": "名前",
|
||||||
|
"common.definition": "定義",
|
||||||
|
"common.belong-module": "関連モジュール",
|
||||||
|
"common.width": "ビット幅",
|
||||||
|
"common.direction": "方向",
|
||||||
|
"common.input-number": "入力数量",
|
||||||
|
"common.output-number": "出力数量",
|
||||||
|
"common.inout-number": "数量",
|
||||||
|
"common.instance-number": "インスタンス化されたモジュールの数",
|
||||||
|
"common.general-cell-number": "一般デバイスの数"
|
||||||
}
|
}
|
@ -44,5 +44,18 @@
|
|||||||
"setting.pulsation-speed": "펄스 효과 속도",
|
"setting.pulsation-speed": "펄스 효과 속도",
|
||||||
"toolbar.save-as-svg": "현재 뷰를 SVG로 저장",
|
"toolbar.save-as-svg": "현재 뷰를 SVG로 저장",
|
||||||
"toolbar.save-as-pdf": "현재 보기를 PDF로 저장",
|
"toolbar.save-as-pdf": "현재 보기를 PDF로 저장",
|
||||||
"saving": "저장 중"
|
"saving": "저장 중",
|
||||||
|
"info.no-entity-select.cannot-display-view": "선택된 엔티티가 없어 데이터 뷰를 표시할 수 없습니다",
|
||||||
|
"entity-info": "엔티티 정보",
|
||||||
|
"common.type": "유형",
|
||||||
|
"common.name": "이름",
|
||||||
|
"common.definition": "정의",
|
||||||
|
"common.belong-module": "소속 모듈",
|
||||||
|
"common.width": "비트 폭",
|
||||||
|
"common.direction": "방향",
|
||||||
|
"common.input-number": "입력 수량",
|
||||||
|
"common.output-number": "출력 수량",
|
||||||
|
"common.inout-number": "수량",
|
||||||
|
"common.instance-number": "인스턴스화된 모듈 수",
|
||||||
|
"common.general-cell-number": "일반 장치 수"
|
||||||
}
|
}
|
@ -44,5 +44,18 @@
|
|||||||
"setting.pulsation-speed": "Скорость импульсного эффекта",
|
"setting.pulsation-speed": "Скорость импульсного эффекта",
|
||||||
"toolbar.save-as-svg": "Сохранить текущее представление как SVG",
|
"toolbar.save-as-svg": "Сохранить текущее представление как SVG",
|
||||||
"toolbar.save-as-pdf": "Сохранить текущее представление как PDF",
|
"toolbar.save-as-pdf": "Сохранить текущее представление как PDF",
|
||||||
"saving": "Сохранение"
|
"saving": "Сохранение",
|
||||||
|
"info.no-entity-select.cannot-display-view": "Ни одна сущность не выбрана, невозможно отобразить представление данных",
|
||||||
|
"entity-info": "Информация о сущности",
|
||||||
|
"common.type": "Тип",
|
||||||
|
"common.name": "Имя",
|
||||||
|
"common.definition": "Определение",
|
||||||
|
"common.belong-module": "Связанный модуль",
|
||||||
|
"common.width": "Разрядность",
|
||||||
|
"common.direction": "Направление",
|
||||||
|
"common.input-number": "количество ввода",
|
||||||
|
"common.output-number": "количество вывода",
|
||||||
|
"common.inout-number": "Количество",
|
||||||
|
"common.instance-number": "Количество созданных модулей",
|
||||||
|
"common.general-cell-number": "Количество общих устройств"
|
||||||
}
|
}
|
@ -44,5 +44,18 @@
|
|||||||
"setting.pulsation-speed": "脉冲特效速度",
|
"setting.pulsation-speed": "脉冲特效速度",
|
||||||
"toolbar.save-as-svg": "将当前视图保存为 svg",
|
"toolbar.save-as-svg": "将当前视图保存为 svg",
|
||||||
"toolbar.save-as-pdf": "将当前视图保存为 pdf",
|
"toolbar.save-as-pdf": "将当前视图保存为 pdf",
|
||||||
"saving": "保存中"
|
"saving": "保存中",
|
||||||
|
"info.no-entity-select.cannot-display-view": "没有选中任何实体,无法展示数据视图",
|
||||||
|
"entity-info": "实体信息",
|
||||||
|
"common.type": "类型",
|
||||||
|
"common.name": "名字",
|
||||||
|
"common.definition": "定义",
|
||||||
|
"common.belong-module": "所属模块",
|
||||||
|
"common.width": "位宽",
|
||||||
|
"common.direction": "方向",
|
||||||
|
"common.input-number": "input 数量",
|
||||||
|
"common.output-number": "output 数量",
|
||||||
|
"common.inout-number": "inout 数量",
|
||||||
|
"common.instance-number": "例化模块数量",
|
||||||
|
"common.general-cell-number": "通用器件数量"
|
||||||
}
|
}
|
@ -44,5 +44,18 @@
|
|||||||
"setting.pulsation-speed": "脈衝特效速度",
|
"setting.pulsation-speed": "脈衝特效速度",
|
||||||
"toolbar.save-as-svg": "將目前視圖儲存為SVG",
|
"toolbar.save-as-svg": "將目前視圖儲存為SVG",
|
||||||
"toolbar.save-as-pdf": "將目前視圖儲存為PDF",
|
"toolbar.save-as-pdf": "將目前視圖儲存為PDF",
|
||||||
"saving": "保存中"
|
"saving": "保存中",
|
||||||
|
"info.no-entity-select.cannot-display-view": "沒有選中任何實體,無法展示數據視圖",
|
||||||
|
"entity-info": "實體資訊",
|
||||||
|
"common.type": "類型",
|
||||||
|
"common.name": "名字",
|
||||||
|
"common.definition": "定義",
|
||||||
|
"common.belong-module": "所屬模組",
|
||||||
|
"common.width": "位寬",
|
||||||
|
"common.direction": "方向",
|
||||||
|
"common.input-number": "輸入數量",
|
||||||
|
"common.output-number": "輸出數量",
|
||||||
|
"common.inout-number": "數量",
|
||||||
|
"common.instance-number": "實例化模組數量",
|
||||||
|
"common.general-cell-number": "通用器件數量"
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user