Cube-view: 45° diagonal from router, then straight to component

All connectors now start with 45° diagonal from router edge,
then go straight (vertical/horizontal) to the component block.
Applies to PE, M_CPU/SRAM, PE→HBM, and UCIe connectors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 00:25:41 -07:00
parent d3de982ea4
commit bde76ec959
2 changed files with 97 additions and 79 deletions
+63 -45
View File
@@ -632,47 +632,50 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
f'text-anchor="middle" font-family="monospace" font-size="{font_sz}" '
f'font-weight="bold" fill="{style["text"]}">{_escape(label)}</text>'
)
# Connector line: block → router (45° L-bend)
# Connector line: router → component (diagonal out from router, then straight)
sc = style["stroke"]
if kind in ("mcpu", "sram"):
# From block right edge, 45° bend to router
x1 = bx + blk_w
# Router → 45° diagonal → horizontal to block
x1 = bx + blk_w # block right edge
y1 = by + blk_h / 2
x2 = px - r_size
x2 = px - r_size # router left edge
y2 = py
# 45° bend: go horizontal first, then diagonal
mid_x = x2 - abs(y2 - y1)
dy = abs(y2 - y1)
# From router: diagonal 45° toward block, then horizontal
mid_x = x2 - dy # 45° means dx == dy
if mid_x < x1:
mid_x = (x1 + x2) / 2
mid_x = x1
parts.append(
f' <polyline points="{x1:.0f},{y1:.0f} {mid_x:.0f},{y1:.0f} {x2:.0f},{y2:.0f}" '
f' <polyline points="{x2:.0f},{y2:.0f} {mid_x:.0f},{y1:.0f} {x1:.0f},{y1:.0f}" '
f'fill="none" stroke="{sc}" stroke-width="1" opacity="0.6"/>'
)
else:
# PE: from block bottom/top edge, 45° bend to router
# PE: Router → 45° diagonal → vertical to block
if is_top:
x1 = bx + blk_w / 2 + offset_x
y1 = by + blk_h
x2 = px
y2 = py - r_size
# 45° bend: go vertical first, then diagonal
mid_y = y2 - abs(x2 - x1)
x1 = bx + blk_w / 2 + offset_x # block center
y1 = by + blk_h # block bottom
x2 = px # router center
y2 = py - r_size # router top
dx = abs(x2 - x1)
# From router: 45° diagonal, then vertical to block
mid_y = y2 - dx
if mid_y < y1:
mid_y = (y1 + y2) / 2
mid_y = y1
parts.append(
f' <polyline points="{x1:.0f},{y1:.0f} {x1:.0f},{mid_y:.0f} {x2:.0f},{y2:.0f}" '
f' <polyline points="{x2:.0f},{y2:.0f} {x1:.0f},{mid_y:.0f} {x1:.0f},{y1:.0f}" '
f'fill="none" stroke="{sc}" stroke-width="1" opacity="0.6"/>'
)
else:
x1 = bx + blk_w / 2 + offset_x
y1 = by
y1 = by # block top
x2 = px
y2 = py + r_size
mid_y = y2 + abs(x2 - x1)
y2 = py + r_size # router bottom
dx = abs(x2 - x1)
mid_y = y2 + dx
if mid_y > y1:
mid_y = (y1 + y2) / 2
mid_y = y1
parts.append(
f' <polyline points="{x1:.0f},{y1:.0f} {x1:.0f},{mid_y:.0f} {x2:.0f},{y2:.0f}" '
f' <polyline points="{x2:.0f},{y2:.0f} {x1:.0f},{mid_y:.0f} {x1:.0f},{y1:.0f}" '
f'fill="none" stroke="{sc}" stroke-width="1" opacity="0.6"/>'
)
@@ -694,14 +697,20 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
rpx, rpy = mm2px(rx, ry)
tgx, tgy = _pe_hbm_targets[pe_id]
r_edge_y = rpy + r_size if rpy < hbm_y else rpy - r_size
# 45° L-bend: vertical from router, then diagonal to HBM port
mid_y = tgy - abs(tgx - rpx) if rpy < hbm_y else tgy + abs(tgx - rpx)
# From router: 45° diagonal toward HBM port, then vertical to port
dx = abs(tgx - rpx)
if rpy < hbm_y:
mid_y = max(mid_y, (r_edge_y + tgy) / 2)
# Top half: router bottom → 45° diagonal → vertical down to HBM top
mid_y = r_edge_y + dx
if mid_y > tgy:
mid_y = tgy
else:
mid_y = min(mid_y, (r_edge_y + tgy) / 2)
# Bottom half: router top → 45° diagonal → vertical up to HBM bottom
mid_y = r_edge_y - dx
if mid_y < tgy:
mid_y = tgy
parts.append(
f' <polyline points="{rpx:.0f},{r_edge_y:.0f} {rpx:.0f},{mid_y:.0f} {tgx:.0f},{tgy:.0f}" '
f' <polyline points="{rpx:.0f},{r_edge_y:.0f} {tgx:.0f},{mid_y:.0f} {tgx:.0f},{tgy:.0f}" '
f'fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" '
f'stroke-dasharray="4,3"/>'
)
@@ -796,42 +805,51 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
f'{conn}</text>'
)
# Connector line: port → router (45° L-bend)
# Connector line: router → UCIe port (diagonal from router, then straight)
rpx, rpy = mm2px(crx, cry)
if direction == "N":
x1, y1 = lx, cy_box + ch
x2, y2 = rpx, rpy - r_size
mid_y = y2 - abs(x2 - x1)
mid_y = max(mid_y, (y1 + y2) / 2)
# Router top → 45° diagonal → vertical to UCIe port
x2, y2 = rpx, rpy - r_size # router top
x1, y1 = lx, cy_box + ch # port bottom
dx = abs(x1 - x2)
mid_y = y2 - dx
if mid_y < y1:
mid_y = y1
parts.append(
f' <polyline points="{x1:.0f},{y1:.0f} {x1:.0f},{mid_y:.0f} {x2:.0f},{y2:.0f}" '
f' <polyline points="{x2:.0f},{y2:.0f} {x1:.0f},{mid_y:.0f} {x1:.0f},{y1:.0f}" '
f'fill="none" stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
)
elif direction == "S":
x1, y1 = lx, cy_box
x2, y2 = rpx, rpy + r_size
mid_y = y2 + abs(x2 - x1)
mid_y = min(mid_y, (y1 + y2) / 2)
x1, y1 = lx, cy_box
dx = abs(x1 - x2)
mid_y = y2 + dx
if mid_y > y1:
mid_y = y1
parts.append(
f' <polyline points="{x1:.0f},{y1:.0f} {x1:.0f},{mid_y:.0f} {x2:.0f},{y2:.0f}" '
f' <polyline points="{x2:.0f},{y2:.0f} {x1:.0f},{mid_y:.0f} {x1:.0f},{y1:.0f}" '
f'fill="none" stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
)
elif direction == "W":
x1, y1 = cx + cw, cy_box + ch / 2
x2, y2 = rpx - r_size, rpy
mid_x = x2 - abs(y2 - y1)
mid_x = max(mid_x, (x1 + x2) / 2)
x1, y1 = cx + cw, cy_box + ch / 2
dy = abs(y1 - y2)
mid_x = x2 - dy
if mid_x < x1:
mid_x = x1
parts.append(
f' <polyline points="{x1:.0f},{y1:.0f} {mid_x:.0f},{y1:.0f} {x2:.0f},{y2:.0f}" '
f' <polyline points="{x2:.0f},{y2:.0f} {mid_x:.0f},{y1:.0f} {x1:.0f},{y1:.0f}" '
f'fill="none" stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
)
elif direction == "E":
x1, y1 = cx, cy_box + ch / 2
x2, y2 = rpx + r_size, rpy
mid_x = x2 + abs(y2 - y1)
mid_x = min(mid_x, (x1 + x2) / 2)
x1, y1 = cx, cy_box + ch / 2
dy = abs(y1 - y2)
mid_x = x2 + dy
if mid_x > x1:
mid_x = x1
parts.append(
f' <polyline points="{x1:.0f},{y1:.0f} {mid_x:.0f},{y1:.0f} {x2:.0f},{y2:.0f}" '
f' <polyline points="{x2:.0f},{y2:.0f} {mid_x:.0f},{y1:.0f} {x1:.0f},{y1:.0f}" '
f'fill="none" stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
)