diff --git a/docs/diagrams/cube_view.svg b/docs/diagrams/cube_view.svg
index 54b0cbf..bdd7536 100644
--- a/docs/diagrams/cube_view.svg
+++ b/docs/diagrams/cube_view.svg
@@ -241,62 +241,62 @@
256GB/s
256GB/s
-
- UCIe-W
-
- c0
-
-
- c1
-
-
- c2
-
-
- c3
-
-
- UCIe-N
-
- c0
-
-
- c1
-
-
- c2
-
-
- c3
-
-
- UCIe-E
-
- c0
-
-
- c1
-
-
- c2
-
-
- c3
-
-
- UCIe-S
-
- c0
-
-
- c1
-
-
- c2
-
-
- c3
-
+
+ UCIe-W
+
+ c0
+
+
+ c1
+
+
+ c2
+
+
+ c3
+
+
+ UCIe-N
+
+ c0
+
+
+ c1
+
+
+ c2
+
+
+ c3
+
+
+ UCIe-E
+
+ c0
+
+
+ c1
+
+
+ c2
+
+
+ c3
+
+
+ UCIe-S
+
+ c0
+
+
+ c1
+
+
+ c2
+
+
+ c3
+
PE Router
diff --git a/src/kernbench/topology/visualizer.py b/src/kernbench/topology/visualizer.py
index e19de17..6c42213 100644
--- a/src/kernbench/topology/visualizer.py
+++ b/src/kernbench/topology/visualizer.py
@@ -683,9 +683,18 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
f'{agg_bw:.0f}GB/s'
)
- # ── UCIe port components (inside cube boundary, on edges) ──
+ # ── UCIe port components (position/size from topology.yaml) ──
+ # ucie_mm.size = 2.0mm, positions from _cube_local_positions
+ ucie_size_mm = cube.get("geometry", {}).get("ucie_mm", {}).get("size", 2.0)
+ ucie_positions = {
+ "N": (cube_w / 2, ucie_size_mm / 2), # top center
+ "S": (cube_w / 2, cube_h - ucie_size_mm / 2), # bottom center
+ "W": (ucie_size_mm / 2, cube_h / 2), # left center
+ "E": (cube_w - ucie_size_mm / 2, cube_h / 2), # right center
+ }
+
# Collect UCIe connections per direction
- ucie_by_dir: dict[str, list[tuple[str, str, float, float]]] = {} # dir → [(conn, rkey, rx, ry)]
+ ucie_by_dir: dict[str, list[tuple[str, str, float, float]]] = {}
for rkey, rval in routers.items():
if rval is None:
continue
@@ -699,123 +708,86 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
ucie_by_dir.setdefault(direction, []).append((conn, rkey, rx, ry))
ucie_colors = ["#818cf8", "#a78bfa", "#c084fc", "#e879f9"]
- ucie_port_inset = 3 # mm inset from cube edge
for direction, conns in ucie_by_dir.items():
- conns.sort(key=lambda x: x[0]) # sort by conn name
+ conns.sort(key=lambda x: x[0])
n_conn = len(conns)
+ ucx_mm, ucy_mm = ucie_positions.get(direction, (cube_w / 2, cube_h / 2))
+ ucx, ucy = mm2px(ucx_mm, ucy_mm)
- # UCIe component box position (inside cube, along edge)
- if direction == "N":
- # Horizontal bar along top edge
- # Find X span from attached routers
- xs = [mm2px(rx, ry)[0] for _, _, rx, ry in conns]
- ux1 = min(xs) - 15
- ux2 = max(xs) + 15
- uw = ux2 - ux1
- uh = 18
- ux = ux1
- uy = pad + ucie_port_inset * scale
- elif direction == "S":
- xs = [mm2px(rx, ry)[0] for _, _, rx, ry in conns]
- ux1 = min(xs) - 15
- ux2 = max(xs) + 15
- uw = ux2 - ux1
- uh = 18
- ux = ux1
- uy = pad + cube_h * scale - ucie_port_inset * scale - uh
- elif direction == "W":
- ys = [mm2px(rx, ry)[1] for _, _, rx, ry in conns]
- uy1 = min(ys) - 15
- uy2 = max(ys) + 15
- uw = 18
- uh = uy2 - uy1
- ux = pad + ucie_port_inset * scale
- uy = uy1
- elif direction == "E":
- ys = [mm2px(rx, ry)[1] for _, _, rx, ry in conns]
- uy1 = min(ys) - 15
- uy2 = max(ys) + 15
- uw = 18
- uh = uy2 - uy1
- ux = pad + cube_w * scale - ucie_port_inset * scale - uw
- uy = uy1
+ # UCIe box: size from topology, N/S horizontal, E/W vertical
+ us = ucie_size_mm * scale
+ if direction in ("N", "S"):
+ uw, uh = us, us * 0.5
else:
- continue
+ uw, uh = us * 0.5, us
+
+ ux = ucx - uw / 2
+ uy = ucy - uh / 2
# UCIe component background
parts.append(
f' '
+ f'rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.9"/>'
+ )
+ # UCIe direction label
+ parts.append(
+ f' '
+ f'UCIe-{direction}'
)
- # UCIe label
- if direction in ("N", "S"):
- parts.append(
- f' '
- f'UCIe-{direction}'
- )
- else:
- parts.append(
- f' '
- f'UCIe-{direction}'
- )
# Connection port boxes inside UCIe component
for ci, (conn, rkey, crx, cry) in enumerate(conns):
c_color = ucie_colors[ci % len(ucie_colors)]
if direction in ("N", "S"):
- # Horizontal layout
cw = max((uw - 4) / n_conn - 1, 6)
ch = uh - 4
cx = ux + 2 + ci * (cw + 1)
- cy = uy + 2
+ cy_box = uy + 2
else:
- # Vertical layout
cw = uw - 4
ch = max((uh - 4) / n_conn - 1, 6)
cx = ux + 2
- cy = uy + 2 + ci * (ch + 1)
+ cy_box = uy + 2 + ci * (ch + 1)
parts.append(
- f' '
)
- # Connection label
lx = cx + cw / 2
- ly_t = cy + ch / 2 + 3
+ ly_t = cy_box + ch / 2 + 3
parts.append(
f' '
f'{conn}'
)
- # Connector line: port box → attached router
+ # Connector line: port → router
rpx, rpy = mm2px(crx, cry)
if direction == "N":
parts.append(
- f' '
)
elif direction == "S":
parts.append(
- f' '
)
elif direction == "W":
parts.append(
- f' '
)
elif direction == "E":
parts.append(
- f' '
)