实现展示信号基本信息
This commit is contained in:
parent
b142e5d906
commit
6342ebfdc7
@ -1,6 +1,6 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4797805 */
|
||||
src: url('iconfont.woff2?t=1735470843861') format('woff2');
|
||||
src: url('iconfont.woff2?t=1735991360293') format('woff2');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@ -11,6 +11,22 @@
|
||||
-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 {
|
||||
content: "\e600";
|
||||
}
|
||||
@ -243,3 +259,7 @@
|
||||
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 pako from 'pako';
|
||||
|
||||
const mode = window.acquireVsCodeApi === undefined ? 'debug' : 'release';
|
||||
export const mode = window.acquireVsCodeApi === undefined ? 'debug' : 'release';
|
||||
pinkLog('digital-netlist-render mode: ' + mode);
|
||||
|
||||
let vscode = window.acquireVsCodeApi === undefined ? undefined : acquireVsCodeApi();
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="about-wrapper">
|
||||
<div class="about-wrapper" :style="aboutWrapper">
|
||||
<div class="usermanual">
|
||||
<h2>{{ t('usermanual') }}</h2>
|
||||
<div class="usermanual-item">
|
||||
@ -39,8 +39,9 @@
|
||||
|
||||
|
||||
<script setup>
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { horizontalResizer } from '../right-nav';
|
||||
|
||||
defineComponent({ name: 'dide-about' });
|
||||
|
||||
@ -48,7 +49,9 @@ function goto(url) {
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
|
||||
const platform = navigator.platform;
|
||||
const aboutWrapper = computed(() => ({
|
||||
width: horizontalResizer.width - 10 + 'px'
|
||||
}));
|
||||
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
|
@ -1,24 +1,36 @@
|
||||
<template>
|
||||
<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>
|
||||
<hr style="width: 100%;">
|
||||
<el-scrollbar height="86vh" style="padding-right: 7px;">
|
||||
|
||||
<el-scrollbar height="40vh" style="padding-right: 7px;height: 50%;">
|
||||
<modules
|
||||
v-for="mod of treeviewData.modules"
|
||||
:key="mod.name"
|
||||
:module="mod"
|
||||
></modules>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineComponent, onMounted } from 'vue';
|
||||
import { defineComponent, onMounted, computed } from 'vue';
|
||||
|
||||
import modules from './modules.vue';
|
||||
import info from './info.vue';
|
||||
|
||||
import { resize, treeviewData, verticalResizer } from './tree';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { horizontalResizer } from '../right-nav';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@ -31,6 +43,11 @@ onMounted(() => {
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
const netlistModuleStyle = computed(() => ({
|
||||
width: horizontalResizer.width - 30 + 'px'
|
||||
}));
|
||||
|
||||
</script>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
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' });
|
||||
|
||||
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>
|
||||
<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">
|
||||
<div :class="expandManage.expandTagClass"></div>
|
||||
</span>
|
||||
@ -17,10 +20,14 @@
|
||||
<div style="width: 20px;"></div>
|
||||
<div style="width: 100%;">
|
||||
<!-- 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>
|
||||
<span class="iconfont icon-wave-square"></span>
|
||||
<span class="iconfont icon-info-port"></span>
|
||||
 {{ port.name }}
|
||||
</div>
|
||||
|
||||
@ -41,6 +48,7 @@
|
||||
import { globalLookup } from '@/hook/global';
|
||||
import { ModuleView } from '@/hook/render/yosys';
|
||||
import { defineComponent, reactive, computed } from 'vue';
|
||||
import { infoView } from './info';
|
||||
|
||||
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() {
|
||||
@ -110,16 +157,20 @@ const expandManage = reactive({
|
||||
});
|
||||
|
||||
function makeIconClass() {
|
||||
return 'icon-memory-chip';
|
||||
return 'icon-info-module';
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.icon-memory-chip {
|
||||
.module .icon-info-module {
|
||||
color: #FF7043;
|
||||
}
|
||||
|
||||
.module .icon-info-port {
|
||||
color: var(--main-color);
|
||||
}
|
||||
|
||||
.module {
|
||||
text-align: left;
|
||||
}
|
||||
@ -148,6 +199,12 @@ function makeIconClass() {
|
||||
border-radius: .3em;
|
||||
}
|
||||
|
||||
.netlist-treeview-item.active {
|
||||
background-color: var(--sidebar-item-selected);
|
||||
border-radius: .3em;
|
||||
transition: var(--animation-3s);
|
||||
}
|
||||
|
||||
.netlist-treeview-selected {
|
||||
color: #ddd;
|
||||
background-color: var(--button-active) !important;
|
||||
|
@ -68,6 +68,7 @@ export const globalLookup = reactive({
|
||||
|
||||
/**
|
||||
* @description 当前选择的实体,可以是 wire,也可以是 cell
|
||||
* @type {import('./jsdoc').ICurrentSelectEntity}
|
||||
*/
|
||||
currentSelectEntity: undefined,
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
import { Module } from "./render/layout";
|
||||
import { ModuleView } from "./render/yosys";
|
||||
|
||||
/**
|
||||
* @typedef {number | string} WireId 信号ID
|
||||
@ -269,5 +270,25 @@ import { Module } from "./render/layout";
|
||||
|
||||
/**
|
||||
* @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);
|
||||
console.log(constantWidth);
|
||||
|
||||
const constantConnection = {
|
||||
id: dotConnect(id, '0'),
|
||||
|
@ -125,4 +125,9 @@ export class RenderViewNode {
|
||||
this.wireRender.render();
|
||||
|
||||
}
|
||||
|
||||
|
||||
findNode() {
|
||||
|
||||
}
|
||||
}
|
@ -179,6 +179,35 @@ export class ModuleView {
|
||||
get id() {
|
||||
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 {
|
||||
@ -186,7 +215,7 @@ export class Port {
|
||||
* @description port 的抽象
|
||||
* @param {ModuleView} view
|
||||
* @param {string} name
|
||||
* @param {YosysPort} rawPort
|
||||
* @param {import("../jsdoc").YosysPort} rawPort
|
||||
*/
|
||||
constructor(view, name, rawPort) {
|
||||
this.view = view;
|
||||
@ -198,6 +227,10 @@ export class Port {
|
||||
return this.rawPort.bits;
|
||||
}
|
||||
|
||||
get width() {
|
||||
return (this.rawPort.bits || []).length;
|
||||
}
|
||||
|
||||
get direction() {
|
||||
return this.rawPort.direction;
|
||||
}
|
||||
@ -205,6 +238,15 @@ export class Port {
|
||||
get id() {
|
||||
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 {
|
||||
@ -257,6 +299,11 @@ export class Cell {
|
||||
get id() {
|
||||
return dotConnect(this.view.id, this.name);
|
||||
}
|
||||
|
||||
get definition() {
|
||||
const attributes = this.rawCell.attributes;
|
||||
return definitionFromAttribute(attributes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -325,4 +372,25 @@ export class Wire {
|
||||
export function dotConnect(...args) {
|
||||
const stringArgs = args.map(arg => arg.toString());
|
||||
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": "سرعة تأثير النبض",
|
||||
"toolbar.save-as-svg": "حفظ العرض الحالي كـ SVG",
|
||||
"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",
|
||||
"toolbar.save-as-svg": "Aktuelle Ansicht als SVG 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",
|
||||
"toolbar.save-as-svg": "Save current view as SVG",
|
||||
"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",
|
||||
"toolbar.save-as-svg": "Enregistrer la vue actuelle au format SVG",
|
||||
"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": "パルスエフェクト速度",
|
||||
"toolbar.save-as-svg": "現在のビューをSVGとして保存",
|
||||
"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": "펄스 효과 속도",
|
||||
"toolbar.save-as-svg": "현재 뷰를 SVG로 저장",
|
||||
"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": "Скорость импульсного эффекта",
|
||||
"toolbar.save-as-svg": "Сохранить текущее представление как SVG",
|
||||
"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": "脉冲特效速度",
|
||||
"toolbar.save-as-svg": "将当前视图保存为 svg",
|
||||
"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": "脈衝特效速度",
|
||||
"toolbar.save-as-svg": "將目前視圖儲存為SVG",
|
||||
"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