Cube-view: UCIe components inside cube boundary with port boxes
- UCIe-N/S/E/W drawn as component blocks inside cube boundary (inset 3mm from edge) - Each UCIe has c0-c3 connection ports as color-coded boxes inside - Connector lines from each port box to its attached router - Removed old UCIe rendering that placed blocks outside cube Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -599,11 +599,7 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
|
||||
blocks.append(("M_CPU", "mcpu", _COMP_STYLE["mcpu"]))
|
||||
if "sram" in attach:
|
||||
blocks.append(("SRAM", "sram", _COMP_STYLE["sram"]))
|
||||
ucie_items = [a for a in attach if a.startswith("ucie_")]
|
||||
for ui in ucie_items:
|
||||
direction = ui.split(".")[0].replace("ucie_", "").upper()
|
||||
conn = ui.split(".")[1] if "." in ui else ""
|
||||
blocks.append((f"UCIe-{direction}.{conn}", "ucie", _COMP_STYLE["ucie"]))
|
||||
# UCIe handled separately below
|
||||
|
||||
# Position blocks outward from router (away from cube center)
|
||||
for bi, (label, kind, style) in enumerate(blocks):
|
||||
@@ -611,29 +607,7 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
|
||||
# Use left/right offset for multiple blocks on same router
|
||||
offset_x = (bi - (len(blocks) - 1) / 2) * (blk_w + 4)
|
||||
|
||||
if kind == "ucie":
|
||||
# UCIe: place flush against cube edge at router position
|
||||
direction = label.split("-")[1].split(".")[0] if "-" in label else ""
|
||||
ucie_w, ucie_h = 22, 10 # smaller blocks for UCIe ports
|
||||
if direction == "N":
|
||||
bx = px - ucie_w / 2
|
||||
by = pad - ucie_h # flush against top edge
|
||||
blk_w, blk_h = ucie_w, ucie_h
|
||||
elif direction == "S":
|
||||
bx = px - ucie_w / 2
|
||||
by = pad + cube_h * scale # flush against bottom edge
|
||||
blk_w, blk_h = ucie_w, ucie_h
|
||||
elif direction == "W":
|
||||
bx = pad - ucie_w # flush against left edge
|
||||
by = py - ucie_h / 2
|
||||
blk_w, blk_h = ucie_w, ucie_h
|
||||
elif direction == "E":
|
||||
bx = pad + cube_w * scale # flush against right edge
|
||||
by = py - ucie_h / 2
|
||||
blk_w, blk_h = ucie_w, ucie_h
|
||||
else:
|
||||
bx, by = px - blk_w / 2, py - r_size - blk_h - 4
|
||||
elif kind in ("mcpu", "sram"):
|
||||
if kind in ("mcpu", "sram"):
|
||||
# M_CPU/SRAM: place to the left of router (avoid mesh overlap)
|
||||
bx = px - r_size - blk_w - 6
|
||||
by = py - blk_h / 2 + bi * (blk_h + 2)
|
||||
@@ -659,33 +633,7 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
|
||||
f'font-weight="bold" fill="{style["text"]}">{_escape(label)}</text>'
|
||||
)
|
||||
# Connector line: block → router
|
||||
if kind == "ucie":
|
||||
# Line from block edge toward router
|
||||
if direction == "N":
|
||||
parts.append(
|
||||
f' <line x1="{bx + blk_w / 2:.0f}" y1="{by + blk_h:.0f}" '
|
||||
f'x2="{px:.0f}" y2="{py - r_size:.0f}" '
|
||||
f'stroke="{style["stroke"]}" stroke-width="1" opacity="0.6"/>'
|
||||
)
|
||||
elif direction == "S":
|
||||
parts.append(
|
||||
f' <line x1="{bx + blk_w / 2:.0f}" y1="{by:.0f}" '
|
||||
f'x2="{px:.0f}" y2="{py + r_size:.0f}" '
|
||||
f'stroke="{style["stroke"]}" stroke-width="1" opacity="0.6"/>'
|
||||
)
|
||||
elif direction == "W":
|
||||
parts.append(
|
||||
f' <line x1="{bx + blk_w:.0f}" y1="{by + blk_h / 2:.0f}" '
|
||||
f'x2="{px - r_size:.0f}" y2="{py:.0f}" '
|
||||
f'stroke="{style["stroke"]}" stroke-width="1" opacity="0.6"/>'
|
||||
)
|
||||
elif direction == "E":
|
||||
parts.append(
|
||||
f' <line x1="{bx:.0f}" y1="{by + blk_h / 2:.0f}" '
|
||||
f'x2="{px + r_size:.0f}" y2="{py:.0f}" '
|
||||
f'stroke="{style["stroke"]}" stroke-width="1" opacity="0.6"/>'
|
||||
)
|
||||
elif kind in ("mcpu", "sram"):
|
||||
if kind in ("mcpu", "sram"):
|
||||
# Horizontal connector (block right edge → router left edge)
|
||||
parts.append(
|
||||
f' <line x1="{bx + blk_w:.0f}" y1="{by + blk_h / 2:.0f}" '
|
||||
@@ -735,6 +683,143 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
|
||||
f'{agg_bw:.0f}GB/s</text>'
|
||||
)
|
||||
|
||||
# ── UCIe port components (inside cube boundary, on edges) ──
|
||||
# Collect UCIe connections per direction
|
||||
ucie_by_dir: dict[str, list[tuple[str, str, float, float]]] = {} # dir → [(conn, rkey, rx, ry)]
|
||||
for rkey, rval in routers.items():
|
||||
if rval is None:
|
||||
continue
|
||||
rx, ry = rval["pos_mm"]
|
||||
for a in rval.get("attach", []):
|
||||
if not a.startswith("ucie_"):
|
||||
continue
|
||||
parts_a = a.split(".")
|
||||
direction = parts_a[0].replace("ucie_", "").upper()
|
||||
conn = parts_a[1] if len(parts_a) > 1 else "c0"
|
||||
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
|
||||
n_conn = len(conns)
|
||||
|
||||
# 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
|
||||
else:
|
||||
continue
|
||||
|
||||
# UCIe component background
|
||||
parts.append(
|
||||
f' <rect x="{ux:.0f}" y="{uy:.0f}" '
|
||||
f'width="{uw:.0f}" height="{uh:.0f}" '
|
||||
f'rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.8"/>'
|
||||
)
|
||||
# UCIe label
|
||||
if direction in ("N", "S"):
|
||||
parts.append(
|
||||
f' <text x="{ux + uw / 2:.0f}" y="{uy - 3:.0f}" text-anchor="middle" '
|
||||
f'font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">'
|
||||
f'UCIe-{direction}</text>'
|
||||
)
|
||||
else:
|
||||
parts.append(
|
||||
f' <text x="{ux + uw / 2:.0f}" y="{uy - 3:.0f}" text-anchor="middle" '
|
||||
f'font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">'
|
||||
f'UCIe-{direction}</text>'
|
||||
)
|
||||
|
||||
# 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
|
||||
else:
|
||||
# Vertical layout
|
||||
cw = uw - 4
|
||||
ch = max((uh - 4) / n_conn - 1, 6)
|
||||
cx = ux + 2
|
||||
cy = uy + 2 + ci * (ch + 1)
|
||||
|
||||
parts.append(
|
||||
f' <rect x="{cx:.0f}" y="{cy:.0f}" '
|
||||
f'width="{cw:.0f}" height="{ch:.0f}" '
|
||||
f'rx="2" fill="{c_color}" opacity="0.7"/>'
|
||||
)
|
||||
# Connection label
|
||||
lx = cx + cw / 2
|
||||
ly_t = cy + ch / 2 + 3
|
||||
parts.append(
|
||||
f' <text x="{lx:.0f}" y="{ly_t:.0f}" text-anchor="middle" '
|
||||
f'font-family="monospace" font-size="5" fill="white">'
|
||||
f'{conn}</text>'
|
||||
)
|
||||
|
||||
# Connector line: port box → attached router
|
||||
rpx, rpy = mm2px(crx, cry)
|
||||
if direction == "N":
|
||||
parts.append(
|
||||
f' <line x1="{lx:.0f}" y1="{cy + ch:.0f}" '
|
||||
f'x2="{rpx:.0f}" y2="{rpy - r_size:.0f}" '
|
||||
f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
|
||||
)
|
||||
elif direction == "S":
|
||||
parts.append(
|
||||
f' <line x1="{lx:.0f}" y1="{cy:.0f}" '
|
||||
f'x2="{rpx:.0f}" y2="{rpy + r_size:.0f}" '
|
||||
f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
|
||||
)
|
||||
elif direction == "W":
|
||||
parts.append(
|
||||
f' <line x1="{cx + cw:.0f}" y1="{cy + ch / 2:.0f}" '
|
||||
f'x2="{rpx - r_size:.0f}" y2="{rpy:.0f}" '
|
||||
f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
|
||||
)
|
||||
elif direction == "E":
|
||||
parts.append(
|
||||
f' <line x1="{cx:.0f}" y1="{cy + ch / 2:.0f}" '
|
||||
f'x2="{rpx + r_size:.0f}" y2="{rpy:.0f}" '
|
||||
f'stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
|
||||
)
|
||||
|
||||
# ── Legend ──
|
||||
ly = h_px - 35
|
||||
legend_items = [
|
||||
|
||||
Reference in New Issue
Block a user