实现展示信号基本信息

This commit is contained in:
锦恢 2025-01-04 22:45:42 +08:00
parent b142e5d906
commit 6342ebfdc7
23 changed files with 682 additions and 28 deletions

View File

@ -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
View 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;
}

View File

@ -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();

View File

@ -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>

View File

@ -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>

View 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;
}
});

View File

@ -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>

View File

@ -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>
&ensp;{{ port.name }} &ensp;{{ 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;

View File

@ -68,6 +68,7 @@ export const globalLookup = reactive({
/** /**
* @description 当前选择的实体可以是 wire也可以是 cell * @description 当前选择的实体可以是 wire也可以是 cell
* @type {import('./jsdoc').ICurrentSelectEntity}
*/ */
currentSelectEntity: undefined, currentSelectEntity: undefined,

View File

@ -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
*/ */

View File

@ -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'),

View File

@ -125,4 +125,9 @@ export class RenderViewNode {
this.wireRender.render(); this.wireRender.render();
} }
findNode() {
}
} }

View File

@ -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;
}

View File

@ -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": "عدد الأجهزة العامة"
} }

View File

@ -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"
} }

View File

@ -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"
} }

View File

@ -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"
} }

View File

@ -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": "一般デバイスの数"
} }

View File

@ -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": "일반 장치 수"
} }

View File

@ -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": "Количество общих устройств"
} }

View File

@ -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": "通用器件数量"
} }

View File

@ -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": "通用器件數量"
} }