update
This commit is contained in:
parent
d1ab16c5d2
commit
4586b5b19c
13
design/netlist.drawio
Normal file
13
design/netlist.drawio
Normal file
@ -0,0 +1,13 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="SfLhgSYCHkdHWK2D13we" name="第 1 页">
|
||||
<mxGraphModel dx="588" dy="624" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="2" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#6a00ff;fontColor=#ffffff;strokeColor=#3700CC;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="290" width="120" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<!-- 渲染区域 -->
|
||||
<!-- <Render></Render> -->
|
||||
<div id="netlist"></div>
|
||||
<Render></Render>
|
||||
<!-- 右侧工具合集 -->
|
||||
<RightNav></RightNav>
|
||||
</template>
|
||||
|
@ -17,5 +17,8 @@ defineComponent({ name: 'netlist-render' });
|
||||
height: 100vh;
|
||||
width: calc(100vw - var(--right-nav-width));
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
@ -148,6 +148,8 @@
|
||||
/**
|
||||
* @typedef ElkNode
|
||||
* @property {string} id 节点的唯一标识符。
|
||||
* @property {string} [renderName] node 展示的名字,布局算法前生成
|
||||
* @property {'port' | 'cell' | 'cellPort'} [renderType] 渲染的类型
|
||||
* @property {ElkNode[]} children 当前节点的内部
|
||||
* @property {ElkPort[]} ports 当前节点的端口
|
||||
* @property {ElkEdge[]} edges 当前节点的连线
|
||||
@ -188,8 +190,9 @@
|
||||
|
||||
/**
|
||||
* @typedef ElkSection
|
||||
* @property {ElkPoint} startPoint
|
||||
* @property {ElkPoint} endPoint
|
||||
* @property {ElkPoint} startPoint 起点
|
||||
* @property {ElkPoint} endPoint 终点
|
||||
* @property {ElkPoint[]} bendPoints 中间经过的点
|
||||
* @property {string} id edge 的 id
|
||||
* @property {string} incomingShape source 实体的 id
|
||||
* @property {string} outgoingShape target 实体的 id
|
||||
|
@ -25,6 +25,10 @@ export class NetlistRender {
|
||||
*/
|
||||
this.elkGraph = {
|
||||
id: 'root',
|
||||
layoutOptions: {
|
||||
'elk.algorithm': 'layered',
|
||||
'layered.nodePlacement.strategy': 'SIDE_BASED'
|
||||
},
|
||||
children: [],
|
||||
edges: []
|
||||
};
|
||||
@ -67,10 +71,7 @@ export class NetlistRender {
|
||||
* @returns {Promise<ElkNode>}
|
||||
*/
|
||||
async createLayout() {
|
||||
const elk = new ELK({
|
||||
// 分层算法,使得生成的边和坐标轴平行
|
||||
algorithm: 'layered'
|
||||
});
|
||||
const elk = new ELK();
|
||||
const graph = this.elkGraph;
|
||||
const layoutGraph = await elk.layout(graph);
|
||||
console.log(layoutGraph);
|
||||
@ -93,8 +94,8 @@ export class NetlistRender {
|
||||
|
||||
// 遍历计算布局进行创建
|
||||
const svg = d3.select(container).append('svg')
|
||||
.attr('width', this.renderWidth)
|
||||
.attr('height', this.renderHeight);
|
||||
.attr('width', virtualWidth)
|
||||
.attr('height', virtualHeight);
|
||||
|
||||
await this.renderEntity(svg, computedLayout, ratio);
|
||||
await this.renderLine(svg, computedLayout, ratio);
|
||||
@ -122,7 +123,10 @@ export class NetlistRender {
|
||||
y: node.y,
|
||||
width: node.width,
|
||||
height: node.height,
|
||||
fill: 'green'
|
||||
fill: '#2D323B',
|
||||
text: node.renderName,
|
||||
rx: 3,
|
||||
ry: 3
|
||||
});
|
||||
|
||||
// 如果存在 port,绘制 port
|
||||
@ -132,7 +136,10 @@ export class NetlistRender {
|
||||
y: cellPort.y + node.y,
|
||||
width: cellPort.width,
|
||||
height: cellPort.height,
|
||||
fill: 'blue'
|
||||
fill: '#CB81DA',
|
||||
text: '',
|
||||
rx: 0,
|
||||
ry: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -146,8 +153,23 @@ export class NetlistRender {
|
||||
.attr('width', data => data.width)
|
||||
.attr('height', data => data.height)
|
||||
.attr('fill', d => d.fill)
|
||||
.attr('stroke', 'white')
|
||||
.attr('stroke-width', 2);
|
||||
.attr('stroke', '#CB81DA')
|
||||
.attr('stroke-width', 2)
|
||||
.attr('rx', d => d.rx)
|
||||
.attr('ry', d => d.ry);
|
||||
|
||||
|
||||
svg.selectAll('text')
|
||||
.data(squares)
|
||||
.enter()
|
||||
.append('text')
|
||||
.attr('x', data => data.x + data.width / 2) // 文本的 x 坐标(居中)
|
||||
.attr('y', data => data.y + data.height / 2) // 文本的 y 坐标(居中)
|
||||
.attr('dominant-baseline', 'middle') // 文本垂直居中
|
||||
.attr('text-anchor', 'middle') // 文本水平居中
|
||||
.attr('fill', 'white') // 文本颜色
|
||||
.attr('font-size', '12px')
|
||||
.text(data => data.text); // 设置文本内容
|
||||
}
|
||||
|
||||
/**
|
||||
@ -160,14 +182,23 @@ export class NetlistRender {
|
||||
const lines = [];
|
||||
for (const edge of computedLayout.edges) {
|
||||
for (const section of edge.sections || []) {
|
||||
lines.push({
|
||||
x1: section.startPoint.x,
|
||||
y1: section.startPoint.y,
|
||||
x2: section.endPoint.x,
|
||||
y2: section.endPoint.y,
|
||||
strokeWidth: 2,
|
||||
color: 'white'
|
||||
});
|
||||
const points = [];
|
||||
points.push(section.startPoint);
|
||||
for (const point of section.bendPoints || []) {
|
||||
points.push(point);
|
||||
}
|
||||
points.push(section.endPoint);
|
||||
|
||||
for (let i = 0; i < points.length - 1; ++ i) {
|
||||
lines.push({
|
||||
x1: points[i].x,
|
||||
y1: points[i].y,
|
||||
x2: points[i + 1].x,
|
||||
y2: points[i + 1].y,
|
||||
strokeWidth: 2,
|
||||
color: 'var(--foreground)'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,6 +211,6 @@ export class NetlistRender {
|
||||
.attr('x2', data => data.x2)
|
||||
.attr('y2', data => data.y2)
|
||||
.attr('stroke-width', data => data.strokeWidth)
|
||||
.attr('stroke', data => data.color)
|
||||
.attr('stroke', data => data.color);
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ import { CELL_LIBS, ModuleTree } from "./yosys";
|
||||
|
||||
export const LAYOUT_CONSTANT = {
|
||||
PORT_WIDTH: 50,
|
||||
PORT_HEIGHT: 50,
|
||||
PORT_HEIGHT: 20,
|
||||
INSTANTIATION_WIDTH: 50,
|
||||
INSTANTIATION_HEIGHT: 50,
|
||||
CONSTANT_WIDTH: 50,
|
||||
@ -68,10 +68,18 @@ export class Module {
|
||||
for (const name of this.moduleTree.nameToPort.keys()) {
|
||||
const port = this.moduleTree.nameToPort.get(name);
|
||||
|
||||
const direction = port.direction === 'input' ? 'LEFT': 'RIGHT';
|
||||
|
||||
const node = {
|
||||
id: port.id,
|
||||
renderName: name,
|
||||
renderType: 'port',
|
||||
type: port.direction,
|
||||
width: LAYOUT_CONSTANT.PORT_WIDTH,
|
||||
height: LAYOUT_CONSTANT.PORT_HEIGHT,
|
||||
properties: {
|
||||
'elk.layered.nodePlacement.side': direction
|
||||
}
|
||||
};
|
||||
|
||||
nodes.push(node);
|
||||
@ -103,6 +111,8 @@ export class Module {
|
||||
const portSide = connection.direction === 'input' ? ELK_DIRECTION.LEFT: ELK_DIRECTION.RIGHT;
|
||||
ports.push({
|
||||
id: connection.id,
|
||||
renderName: connectionName,
|
||||
renderType: 'cellPort',
|
||||
width: LAYOUT_CONSTANT.CELL_PORT_WIDTH,
|
||||
height: LAYOUT_CONSTANT.CELL_PORT_HEIGHT,
|
||||
properties: {
|
||||
@ -113,6 +123,8 @@ export class Module {
|
||||
|
||||
const node = {
|
||||
id: cell.id,
|
||||
renderName: cell.type,
|
||||
renderType: 'cell',
|
||||
width,
|
||||
height,
|
||||
ports,
|
||||
@ -156,6 +168,7 @@ export class Module {
|
||||
// 如果是常数,需要先创建代表常数的节点,常数一定是器件的输入,而非输出
|
||||
const node = {
|
||||
id,
|
||||
name: wireId,
|
||||
width: LAYOUT_CONSTANT.CONSTANT_WIDTH,
|
||||
height: LAYOUT_CONSTANT.CONSTANT_HEIGHT,
|
||||
layoutOptions: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user