修复 netlist bug

This commit is contained in:
锦恢 2025-01-02 03:38:46 +08:00
parent f148e9a24f
commit c4c6605174
7 changed files with 793 additions and 17 deletions

View File

@ -15,7 +15,7 @@
<script> <script>
window.readNetFile = async () => { window.readNetFile = async () => {
const inputVcdFile = 'full_adder.json'; const inputVcdFile = 'IF_ID.json';
const skin = 'dide.skin'; const skin = 'dide.skin';
const r1 = await fetch(inputVcdFile); const r1 = await fetch(inputVcdFile);
const r2 = await fetch(skin); const r2 = await fetch(skin);
@ -23,7 +23,7 @@
const skinBinary = await r2.arrayBuffer(); const skinBinary = await r2.arrayBuffer();
return [ netJson, skinBinary ]; return [ netJson, skinBinary ];
} }
window.moduleName = 'full_adder'; window.moduleName = 'IF_ID';
// window.avoidWasm = 'avoid.wasm'; // window.avoidWasm = 'avoid.wasm';
</script> </script>
</head> </head>

630
public/netlist.json Normal file
View File

@ -0,0 +1,630 @@
{
"creator": "Yosys 0.48+5 (git sha1 7a362f1f7, clang++ 18.1.2-wasi-sdk -Oz)",
"modules": {
"netlistview": {
"attributes": {
"cells_not_processed": "00000000000000000000000000000001",
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:2.1-36.10"
},
"ports": {
"clock": {
"direction": "input",
"bits": [ 2 ]
},
"data_in": {
"direction": "input",
"bits": [ 3, 4, 5, 6, 7, 8, 9, 10, 11 ]
},
"up": {
"direction": "input",
"bits": [ 12 ]
},
"down": {
"direction": "input",
"bits": [ 13 ]
},
"carry_out": {
"direction": "output",
"bits": [ 14 ]
},
"borrow_out": {
"direction": "output",
"bits": [ 15 ]
},
"count_out": {
"direction": "output",
"bits": [ 16, 17, 18, 19, 20, 21, 22, 23, 24 ]
},
"parity_out": {
"direction": "output",
"bits": [ 25 ]
}
},
"cells": {
"$add$/dide/user/src/language/vlog/netlistview/netlistview.v:15$3": {
"hide_name": 1,
"type": "$add",
"parameters": {
"A_SIGNED": "00000000000000000000000000000000",
"A_WIDTH": "00000000000000000000000000001001",
"B_SIGNED": "00000000000000000000000000000000",
"B_WIDTH": "00000000000000000000000000000010",
"Y_WIDTH": "00000000000000000000000000001010"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:15.18-15.36"
},
"port_directions": {
"A": "input",
"B": "input",
"Y": "output"
},
"connections": {
"A": [ 16, 17, 18, 19, 20, 21, 22, 23, 24 ],
"B": [ "1", "1" ],
"Y": [ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 ]
}
},
"$and$/dide/user/src/language/vlog/netlistview/netlistview.v:31$5": {
"hide_name": 1,
"type": "$and",
"parameters": {
"A_SIGNED": "00000000000000000000000000000000",
"A_WIDTH": "00000000000000000000000000000001",
"B_SIGNED": "00000000000000000000000000000000",
"B_WIDTH": "00000000000000000000000000000001",
"Y_WIDTH": "00000000000000000000000000000001"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:31.24-31.38"
},
"port_directions": {
"A": "input",
"B": "input",
"Y": "output"
},
"connections": {
"A": [ 12 ],
"B": [ 35 ],
"Y": [ 36 ]
}
},
"$and$/dide/user/src/language/vlog/netlistview/netlistview.v:32$6": {
"hide_name": 1,
"type": "$and",
"parameters": {
"A_SIGNED": "00000000000000000000000000000000",
"A_WIDTH": "00000000000000000000000000000001",
"B_SIGNED": "00000000000000000000000000000000",
"B_WIDTH": "00000000000000000000000000000001",
"Y_WIDTH": "00000000000000000000000000000001"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:32.24-32.40"
},
"port_directions": {
"A": "input",
"B": "input",
"Y": "output"
},
"connections": {
"A": [ 13 ],
"B": [ 37 ],
"Y": [ 38 ]
}
},
"$procdff$12": {
"hide_name": 1,
"type": "$dff",
"parameters": {
"CLK_POLARITY": "1",
"WIDTH": "00000000000000000000000000001001"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
},
"port_directions": {
"CLK": "input",
"D": "input",
"Q": "output"
},
"connections": {
"CLK": [ 2 ],
"D": [ 39, 40, 41, 42, 43, 44, 45, 46, 47 ],
"Q": [ 16, 17, 18, 19, 20, 21, 22, 23, 24 ]
}
},
"$procdff$13": {
"hide_name": 1,
"type": "$dff",
"parameters": {
"CLK_POLARITY": "1",
"WIDTH": "00000000000000000000000000000001"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
},
"port_directions": {
"CLK": "input",
"D": "input",
"Q": "output"
},
"connections": {
"CLK": [ 2 ],
"D": [ 36 ],
"Q": [ 14 ]
}
},
"$procdff$14": {
"hide_name": 1,
"type": "$dff",
"parameters": {
"CLK_POLARITY": "1",
"WIDTH": "00000000000000000000000000000001"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
},
"port_directions": {
"CLK": "input",
"D": "input",
"Q": "output"
},
"connections": {
"CLK": [ 2 ],
"D": [ 38 ],
"Q": [ 15 ]
}
},
"$procdff$15": {
"hide_name": 1,
"type": "$dff",
"parameters": {
"CLK_POLARITY": "1",
"WIDTH": "00000000000000000000000000000001"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
},
"port_directions": {
"CLK": "input",
"D": "input",
"Q": "output"
},
"connections": {
"CLK": [ 2 ],
"D": [ 48 ],
"Q": [ 25 ]
}
},
"$procdff$16": {
"hide_name": 1,
"type": "$dff",
"parameters": {
"CLK_POLARITY": "1",
"WIDTH": "00000000000000000000000000001010"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
},
"port_directions": {
"CLK": "input",
"D": "input",
"Q": "output"
},
"connections": {
"CLK": [ 2 ],
"D": [ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 ],
"Q": [ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58 ]
}
},
"$procdff$17": {
"hide_name": 1,
"type": "$dff",
"parameters": {
"CLK_POLARITY": "1",
"WIDTH": "00000000000000000000000000001010"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
},
"port_directions": {
"CLK": "input",
"D": "input",
"Q": "output"
},
"connections": {
"CLK": [ 2 ],
"D": [ 59, 60, 61, 62, 63, 64, 65, 66, 67, 37 ],
"Q": [ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77 ]
}
},
"$procdff$18": {
"hide_name": 1,
"type": "$dff",
"parameters": {
"CLK_POLARITY": "1",
"WIDTH": "00000000000000000000000000001001"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
},
"port_directions": {
"CLK": "input",
"D": "input",
"Q": "output"
},
"connections": {
"CLK": [ 2 ],
"D": [ 39, 40, 41, 42, 43, 44, 45, 46, 47 ],
"Q": [ 78, 79, 80, 81, 82, 83, 84, 85, 86 ]
}
},
"$procmux$10_CMP0": {
"hide_name": 1,
"type": "$eq",
"parameters": {
"A_SIGNED": "00000000000000000000000000000000",
"A_WIDTH": "00000000000000000000000000000010",
"B_SIGNED": "00000000000000000000000000000000",
"B_WIDTH": "00000000000000000000000000000010",
"Y_WIDTH": "00000000000000000000000000000001"
},
"attributes": {
"full_case": "00000000000000000000000000000001",
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:0.0-0.0|/dide/user/src/language/vlog/netlistview/netlistview.v:17.9-28.16"
},
"port_directions": {
"A": "input",
"B": "input",
"Y": "output"
},
"connections": {
"A": [ 13, 12 ],
"B": [ "1", "0" ],
"Y": [ 87 ]
}
},
"$procmux$11_CMP0": {
"hide_name": 1,
"type": "$logic_not",
"parameters": {
"A_SIGNED": "00000000000000000000000000000000",
"A_WIDTH": "00000000000000000000000000000010",
"Y_WIDTH": "00000000000000000000000000000001"
},
"attributes": {
"full_case": "00000000000000000000000000000001",
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:0.0-0.0|/dide/user/src/language/vlog/netlistview/netlistview.v:17.9-28.16"
},
"port_directions": {
"A": "input",
"Y": "output"
},
"connections": {
"A": [ 13, 12 ],
"Y": [ 88 ]
}
},
"$procmux$7": {
"hide_name": 1,
"type": "$pmux",
"parameters": {
"S_WIDTH": "00000000000000000000000000000100",
"WIDTH": "00000000000000000000000000001001"
},
"attributes": {
"full_case": "00000000000000000000000000000001",
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:0.0-0.0|/dide/user/src/language/vlog/netlistview/netlistview.v:17.9-28.16"
},
"port_directions": {
"A": "input",
"B": "input",
"S": "input",
"Y": "output"
},
"connections": {
"A": [ "x", "x", "x", "x", "x", "x", "x", "x", "x" ],
"B": [ 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 59, 60, 61, 62, 63, 64, 65, 66, 67, 3, 4, 5, 6, 7, 8, 9, 10, 11 ],
"S": [ 89, 90, 87, 88 ],
"Y": [ 39, 40, 41, 42, 43, 44, 45, 46, 47 ]
}
},
"$procmux$8_CMP0": {
"hide_name": 1,
"type": "$eq",
"parameters": {
"A_SIGNED": "00000000000000000000000000000000",
"A_WIDTH": "00000000000000000000000000000010",
"B_SIGNED": "00000000000000000000000000000000",
"B_WIDTH": "00000000000000000000000000000010",
"Y_WIDTH": "00000000000000000000000000000001"
},
"attributes": {
"full_case": "00000000000000000000000000000001",
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:0.0-0.0|/dide/user/src/language/vlog/netlistview/netlistview.v:17.9-28.16"
},
"port_directions": {
"A": "input",
"B": "input",
"Y": "output"
},
"connections": {
"A": [ 13, 12 ],
"B": [ "1", "1" ],
"Y": [ 89 ]
}
},
"$procmux$9_CMP0": {
"hide_name": 1,
"type": "$eq",
"parameters": {
"A_SIGNED": "00000000000000000000000000000000",
"A_WIDTH": "00000000000000000000000000000010",
"B_SIGNED": "00000000000000000000000000000000",
"B_WIDTH": "00000000000000000000000000000010",
"Y_WIDTH": "00000000000000000000000000000001"
},
"attributes": {
"full_case": "00000000000000000000000000000001",
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:0.0-0.0|/dide/user/src/language/vlog/netlistview/netlistview.v:17.9-28.16"
},
"port_directions": {
"A": "input",
"B": "input",
"Y": "output"
},
"connections": {
"A": [ 13, 12 ],
"B": [ "0", "1" ],
"Y": [ 90 ]
}
},
"$reduce_xor$/dide/user/src/language/vlog/netlistview/netlistview.v:30$4": {
"hide_name": 1,
"type": "$reduce_xor",
"parameters": {
"A_SIGNED": "00000000000000000000000000000000",
"A_WIDTH": "00000000000000000000000000001001",
"Y_WIDTH": "00000000000000000000000000000001"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:30.24-30.34"
},
"port_directions": {
"A": "input",
"Y": "output"
},
"connections": {
"A": [ 39, 40, 41, 42, 43, 44, 45, 46, 47 ],
"Y": [ 48 ]
}
},
"$sub$/dide/user/src/language/vlog/netlistview/netlistview.v:14$2": {
"hide_name": 1,
"type": "$sub",
"parameters": {
"A_SIGNED": "00000000000000000000000000000000",
"A_WIDTH": "00000000000000000000000000001001",
"B_SIGNED": "00000000000000000000000000000000",
"B_WIDTH": "00000000000000000000000000000011",
"Y_WIDTH": "00000000000000000000000000001010"
},
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:14.18-14.37"
},
"port_directions": {
"A": "input",
"B": "input",
"Y": "output"
},
"connections": {
"A": [ 16, 17, 18, 19, 20, 21, 22, 23, 24 ],
"B": [ "1", "0", "1" ],
"Y": [ 59, 60, 61, 62, 63, 64, 65, 66, 67, 37 ]
}
}
},
"netnames": {
"$0\\borrow_out[0:0]": {
"hide_name": 1,
"bits": [ 38 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
}
},
"$0\\carry_out[0:0]": {
"hide_name": 1,
"bits": [ 36 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
}
},
"$0\\cnt_dn[9:0]": {
"hide_name": 1,
"bits": [ 59, 60, 61, 62, 63, 64, 65, 66, 67, 37 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
}
},
"$0\\cnt_up[9:0]": {
"hide_name": 1,
"bits": [ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
}
},
"$0\\count_nxt[8:0]": {
"hide_name": 1,
"bits": [ 39, 40, 41, 42, 43, 44, 45, 46, 47 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
}
},
"$0\\count_out[8:0]": {
"hide_name": 1,
"bits": [ 39, 40, 41, 42, 43, 44, 45, 46, 47 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
}
},
"$0\\parity_out[0:0]": {
"hide_name": 1,
"bits": [ 48 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
}
},
"$1\\count_nxt[8:0]": {
"hide_name": 1,
"bits": [ 39, 40, 41, 42, 43, 44, 45, 46, 47 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:13.5-34.8"
}
},
"$add$/dide/user/src/language/vlog/netlistview/netlistview.v:15$3_Y": {
"hide_name": 1,
"bits": [ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:15.18-15.36"
}
},
"$and$/dide/user/src/language/vlog/netlistview/netlistview.v:31$5_Y": {
"hide_name": 1,
"bits": [ 36 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:31.24-31.38"
}
},
"$and$/dide/user/src/language/vlog/netlistview/netlistview.v:32$6_Y": {
"hide_name": 1,
"bits": [ 38 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:32.24-32.40"
}
},
"$procmux$10_CMP": {
"hide_name": 1,
"bits": [ 87 ],
"attributes": {
}
},
"$procmux$11_CMP": {
"hide_name": 1,
"bits": [ 88 ],
"attributes": {
}
},
"$procmux$7_Y": {
"hide_name": 1,
"bits": [ 39, 40, 41, 42, 43, 44, 45, 46, 47 ],
"attributes": {
}
},
"$procmux$8_CMP": {
"hide_name": 1,
"bits": [ 89 ],
"attributes": {
}
},
"$procmux$9_CMP": {
"hide_name": 1,
"bits": [ 90 ],
"attributes": {
}
},
"$reduce_xor$/dide/user/src/language/vlog/netlistview/netlistview.v:30$4_Y": {
"hide_name": 1,
"bits": [ 48 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:30.24-30.34"
}
},
"$sub$/dide/user/src/language/vlog/netlistview/netlistview.v:14$2_Y": {
"hide_name": 1,
"bits": [ 59, 60, 61, 62, 63, 64, 65, 66, 67, 37 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:14.18-14.37"
}
},
"borrow_out": {
"hide_name": 0,
"bits": [ 15 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:8.27-8.37"
}
},
"carry_out": {
"hide_name": 0,
"bits": [ 14 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:8.16-8.25"
}
},
"clock": {
"hide_name": 0,
"bits": [ 2 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:5.11-5.16"
}
},
"cnt_dn": {
"hide_name": 0,
"bits": [ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:10.23-10.29"
}
},
"cnt_up": {
"hide_name": 0,
"bits": [ 49, 50, 51, 52, 53, 54, 55, 56, 57, 58 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:10.15-10.21"
}
},
"count_nxt": {
"hide_name": 0,
"bits": [ 78, 79, 80, 81, 82, 83, 84, 85, 86 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:11.15-11.24"
}
},
"count_out": {
"hide_name": 0,
"bits": [ 16, 17, 18, 19, 20, 21, 22, 23, 24 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:7.22-7.31"
}
},
"data_in": {
"hide_name": 0,
"bits": [ 3, 4, 5, 6, 7, 8, 9, 10, 11 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:4.17-4.24"
}
},
"down": {
"hide_name": 0,
"bits": [ 13 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:5.22-5.26"
}
},
"parity_out": {
"hide_name": 0,
"bits": [ 25 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:8.39-8.49"
}
},
"up": {
"hide_name": 0,
"bits": [ 12 ],
"attributes": {
"src": "/dide/user/src/language/vlog/netlistview/netlistview.v:5.18-5.20"
}
}
}
}
}
}

35
public/netlist.v Normal file
View File

@ -0,0 +1,35 @@
module netlistview(clock, data_in, up, down, carry_out, borrow_out, count_out, parity_out);
input [8:0] data_in;
input clock, up, down;
output reg [8:0] count_out;
output reg carry_out, borrow_out, parity_out;
reg [9:0] cnt_up, cnt_dn;
reg [8:0] count_nxt;
always @(posedge clock) begin
cnt_dn = count_out - 3'b 101;
cnt_up = count_out + 2'b 11;
case ({up,down})
2'b 00 :
count_nxt = data_in;
2'b 01 :
count_nxt = cnt_dn;
2'b 10 :
count_nxt = cnt_up;
2'b 11 :
count_nxt = count_out;
default :
count_nxt = 9'bX;
endcase
parity_out <= ^count_nxt;
carry_out <= up & cnt_up[9];
borrow_out <= down & cnt_dn[9];
count_out <= count_nxt;
end
endmodule

View File

@ -277,7 +277,10 @@ export class Module {
// 当前的器件的这个端口和某一个 port 连接 // 当前的器件的这个端口和某一个 port 连接
const port = tree.wireIdToPort.get(wireId); const port = tree.wireIdToPort.get(wireId);
if (port.direction === 'input') { // 器件的端口的方向有比 port 更高的优先级。
// 器件当前的口为 input那么所连接的 port 就必须是 input即便这个 port 是 output
if (connection.direction === 'input') {
const edge = { const edge = {
// id 遵循 sourcePort-targetPort // id 遵循 sourcePort-targetPort
id: makeEdgeId(port.id, connection.id), id: makeEdgeId(port.id, connection.id),
@ -357,15 +360,40 @@ export class Module {
// 统计分配到左右两侧的 port // 统计分配到左右两侧的 port
const leftSideConnections = []; const leftSideConnections = [];
const rightSideConnections = []; const rightSideConnections = [];
const topSideConnections = [];
for (const conn of cell.nameToConnection.values()) { for (const connection of cell.nameToConnection.values()) {
if (conn.direction === 'input') { const yOffset = meta.getPortYOffset(connection.name);
leftSideConnections.push(conn); if (yOffset === 0) {
topSideConnections.push(connection);
} else if (connection.direction === 'input') {
leftSideConnections.push(connection);
} else { } else {
rightSideConnections.push(conn); rightSideConnections.push(connection);
} }
} }
// 计算上侧的
for (let i = 0; i < topSideConnections.length; ++ i) {
const connection = topSideConnections[i];
const xOffset = meta.getPortXOffset(connection.name);
console.log(xOffset);
ports.push({
id: connection.id,
renderName: connection.name,
renderType: 'cellPort',
direction: 'input',
source: 'cell',
isVertical: true,
width: LAYOUT_CONSTANT.CELL_PORT_WIDTH,
height: LAYOUT_CONSTANT.CELL_PORT_HEIGHT,
x: xOffset,
y: 0
});
}
// 计算左侧的 // 计算左侧的
for (let i = 0; i < leftSideConnections.length; ++ i) { for (let i = 0; i < leftSideConnections.length; ++ i) {
const connection = leftSideConnections[i]; const connection = leftSideConnections[i];

View File

@ -45,6 +45,7 @@ export class WireRender {
const beginPoint = points.at(0); const beginPoint = points.at(0);
const endPoint = points.at(-1); const endPoint = points.at(-1);
const lastTwoPoint = points.at(-2);
const sourcePort = id2port.get(edge.sourcePort); const sourcePort = id2port.get(edge.sourcePort);
const targetPort = id2port.get(edge.targetPort); const targetPort = id2port.get(edge.targetPort);
@ -52,15 +53,22 @@ export class WireRender {
const targetMargin = getMarginParamter(targetPort); const targetMargin = getMarginParamter(targetPort);
beginPoint.x -= sourceMargin.rightMargin; beginPoint.x -= sourceMargin.rightMargin;
const direction = judgeDirection(endPoint, lastTwoPoint);
// 特殊情况: targetPort 为 undefined // 特殊情况: targetPort 为 undefined
if (targetPort === undefined) { if (targetPort === undefined) {
const port = id2port.get(edge.orginalTarget); const port = id2port.get(edge.orginalTarget);
// TODO: 检查正确性 // TODO: 检查正确性
endPoint.x -= LAYOUT_CONSTANT.INSTANCE_RIGHT_MARGIN; endPoint.x -= LAYOUT_CONSTANT.INSTANCE_RIGHT_MARGIN;
} else {
// 判断当前的方向
if (direction === 'up' || direction === 'down') {
lastTwoPoint.x += targetMargin.leftMargin + 1;
endPoint.x += targetMargin.leftMargin + 1;
} else { } else {
endPoint.x += targetMargin.leftMargin; endPoint.x += targetMargin.leftMargin;
} }
}
for (let i = 0; i < points.length; ++ i) { for (let i = 0; i < points.length; ++ i) {
// 根据点的信息创建 path // 根据点的信息创建 path
@ -72,12 +80,7 @@ export class WireRender {
const lineSvg = linePaths.join(' '); const lineSvg = linePaths.join(' ');
// 判断当前的朝向 const arrowLocation = getArrowLocation(endPoint, direction, this.arrowWidth, this.arrowHeight);
const direction = endPoint.x > points.at(-2).x ? 'right' : 'left';
const arrowX = direction === 'right' ? endPoint.x - LAYOUT_CONSTANT.CELL_PORT_WIDTH - this.arrowWidth + 2.5:
endPoint.x + LAYOUT_CONSTANT.CELL_PORT_WIDTH - 2.5
const arrowY = endPoint.y - this.arrowHeight / 2;
this.data.push({ this.data.push({
id: this.idCounter, id: this.idCounter,
@ -85,8 +88,8 @@ export class WireRender {
endPoint: points.at(-1), endPoint: points.at(-1),
arrow: { arrow: {
icon: direction + '-arrow', icon: direction + '-arrow',
x: arrowX, x: arrowLocation.x,
y: arrowY, y: arrowLocation.y,
width: this.arrowWidth, width: this.arrowWidth,
height: this.arrowHeight height: this.arrowHeight
}, },
@ -240,3 +243,50 @@ function cubicBezierAnimation(delta, oldVal, newVal) {
delta = 3 * (1 - delta) * (1 - delta) * delta + 3 * (1 - delta) * delta * delta + delta * delta * delta; delta = 3 * (1 - delta) * (1 - delta) * delta + 3 * (1 - delta) * delta * delta + delta * delta * delta;
return (1 - delta) * oldVal + delta * newVal; return (1 - delta) * oldVal + delta * newVal;
} }
/**
*
* @param {import('../jsdoc').ElkPoint} lastPoint
* @param {import('../jsdoc').ElkPoint} lastTowPoint
* @returns {'left' | 'right' | 'up' | 'down'}
*/
function judgeDirection(lastPoint, lastTowPoint) {
if (lastPoint.x !== lastTowPoint.x) {
return lastPoint.x > lastTowPoint.x ? 'right': 'left';
} else {
return lastPoint.y > lastTowPoint.y ? 'down': 'up';
}
}
/**
*
* @param {import('../jsdoc').ElkPoint} lastPoint
* @param {'left' | 'right' | 'up' | 'down'} direction
*/
function getArrowLocation(lastPoint, direction, arrowWidth, arrowHeight) {
switch (direction) {
case 'left':
return {
x: lastPoint.x + LAYOUT_CONSTANT.CELL_PORT_WIDTH - 2.5,
y: lastPoint.y - arrowHeight / 2
};
case 'right':
return {
x: lastPoint.x - LAYOUT_CONSTANT.CELL_PORT_WIDTH - arrowWidth + 2.5,
y: lastPoint.y - arrowHeight / 2
};
case 'up':
return {
x: lastPoint.x + LAYOUT_CONSTANT.CELL_PORT_WIDTH - arrowWidth / 2 - 1,
y: lastPoint.y - arrowHeight / 2
};
case 'down':
return {
x: lastPoint.x + LAYOUT_CONSTANT.CELL_PORT_WIDTH - arrowWidth / 2 - 1,
y: lastPoint.y - arrowHeight / 2 - 5
};
default:
break;
}
}

View File

@ -12,6 +12,14 @@ export const DIDE_DRAW_SVG_STRINGS = [
{ {
name: 'left-arrow', name: 'left-arrow',
source: '<svg t="1735492154881" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2580" width="200" height="200"><path d="M831.7 189.8L831.7 832.2c0 83.4-115 125.2-182.2 66.2l-360.2-315.90000001c-44.8-39.3-44.8-103.7 0-143l360.2-315.89999999c67.20000001-59 182.2-17.2 182.2 66.2z" p-id="2581" fill="#000000"></path></svg>' source: '<svg t="1735492154881" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2580" width="200" height="200"><path d="M831.7 189.8L831.7 832.2c0 83.4-115 125.2-182.2 66.2l-360.2-315.90000001c-44.8-39.3-44.8-103.7 0-143l360.2-315.89999999c67.20000001-59 182.2-17.2 182.2 66.2z" p-id="2581" fill="#000000"></path></svg>'
},
{
name: 'down-arrow',
source: '<svg t="1735758434434" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2581" width="200" height="200"><path d="M189.8 192.3L832.2 192.3c83.4 0 125.2 115 66.2 182.2l-315.90000001 360.2c-39.3 44.8-103.7 44.8-143 0l-315.89999999-360.2c-59-67.20000001-17.2-182.2 66.2-182.2z" p-id="2582" fill="#000000"></path></svg>'
},
{
name: 'up-arrow',
source: '<svg t="1735758511959" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2581" width="200" height="200"><path d="M834.2 831.7L191.8 831.7c-83.4 0-125.2-115-66.2-182.2l315.90000001-360.2c39.3-44.8 103.7-44.8 143 0l315.89999999 360.2c59 67.20000001 17.2 182.2-66.2 182.2z" p-id="2582" fill="#000000"></path></svg>'
} }
]; ];

View File

@ -103,6 +103,11 @@ class SkinMeta {
this.height = parseFloat(element.getAttribute('height')); this.height = parseFloat(element.getAttribute('height'));
this.svgDoc = svgDoc; this.svgDoc = svgDoc;
/**
* @type {Map<string, number>}
*/
this.portToXOffset = new Map();
/** /**
* @type {Map<string, number>} * @type {Map<string, number>}
*/ */
@ -127,4 +132,24 @@ class SkinMeta {
this.portToYOffset.set(portName, yOffset); this.portToYOffset.set(portName, yOffset);
return yOffset; return yOffset;
} }
/**
* @description 获取指定 port 在所在 svg Y 轴的相对偏移量
* @param {string} portName
*/
getPortXOffset(portName) {
if (this.portToXOffset.has(portName)) {
return this.portToXOffset.get(portName);
}
// 没有 hit尝试获取
const pathElement = this.svgDoc.getElementById(portName);
if (pathElement === null) {
return 0;
}
const transform = pathElement.getAttribute('transform');
const offsetnumber = transform.split('(').at(-1).split(' ').at(0);
const xOffset = parseFloat(offsetnumber);
this.portToXOffset.set(portName, xOffset);
return xOffset;
}
} }