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' ' )