From 4586b5b19ca865700181961ac90ab4e89c12021f Mon Sep 17 00:00:00 2001
From: Kirigaya <1193466151@qq.com>
Date: Mon, 23 Dec 2024 00:04:11 +0800
Subject: [PATCH] update
---
design/netlist.drawio | 13 ++++++
src/App.vue | 3 +-
src/components/render/index.vue | 3 ++
src/hook/jsdoc.js | 7 +++-
src/hook/render/index.js | 71 +++++++++++++++++++++++----------
src/hook/render/layout.js | 15 ++++++-
6 files changed, 87 insertions(+), 25 deletions(-)
create mode 100644 design/netlist.drawio
diff --git a/design/netlist.drawio b/design/netlist.drawio
new file mode 100644
index 0000000..788a161
--- /dev/null
+++ b/design/netlist.drawio
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/App.vue b/src/App.vue
index 6b5ad66..5906aeb 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,7 +1,6 @@
-
-
+
diff --git a/src/components/render/index.vue b/src/components/render/index.vue
index 6dbf925..410222d 100644
--- a/src/components/render/index.vue
+++ b/src/components/render/index.vue
@@ -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;
}
\ No newline at end of file
diff --git a/src/hook/jsdoc.js b/src/hook/jsdoc.js
index d637569..8aee47f 100644
--- a/src/hook/jsdoc.js
+++ b/src/hook/jsdoc.js
@@ -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
diff --git a/src/hook/render/index.js b/src/hook/render/index.js
index 460d567..74e65d9 100644
--- a/src/hook/render/index.js
+++ b/src/hook/render/index.js
@@ -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}
*/
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);
@@ -116,13 +117,16 @@ export class NetlistRender {
// 生成用于绘制的 d3 数据结构
const squares = [];
- for (const node of computedLayout.children) {
+ for (const node of computedLayout.children) {
squares.push({
x: node.x,
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);
}
}
\ No newline at end of file
diff --git a/src/hook/render/layout.js b/src/hook/render/layout.js
index 9d246fe..a4133fb 100644
--- a/src/hook/render/layout.js
+++ b/src/hook/render/layout.js
@@ -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,
@@ -67,11 +67,19 @@ export class Module {
// 绘制 ports
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: {