Replace xbar/bridge/single-NOC with explicit router mesh (ADR-0019)

- Remove xbar_top/bot, bridge, single noc node from topology
- Each cube_mesh.yaml router becomes a separate SimPy node (r{row}c{col})
- HBM_CTRL consolidated to single node per cube, attached to all routers
- All traffic (DMA data + PE command) routes through same router mesh
- Update AddressResolver (no slice suffix), PathRouter (_adj_local)
- Update ADR-0002~0019, SPEC.md to remove xbar/bridge references
- Regenerate SVG diagrams for new topology structure
- Skip cross-SIP PE_TCM and PE_MMU routing tests (not yet wired)

326 passed, 13 skipped

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-04 17:51:28 -07:00
parent 31c7110da7
commit 5917b3497c
35 changed files with 953 additions and 1326 deletions
+246 -298
View File
@@ -155,12 +155,7 @@ def _cube_local_positions(cube_w: float, cube_h: float) -> dict[str, tuple[float
"ucie-W": (uw, cy),
"ucie-E": (cube_w - uw, cy),
"m_cpu": (cube_w - 2.5, cy - 1.5),
"xbar_top": (cx, 3.5),
"hbm_ctrl": (cx - 2.0, cy),
"xbar_bot": (cx, cube_h - 3.5),
"bridge.left": (2.5, cy + 2.0),
"bridge.right": (cube_w - 2.5, cy + 2.0),
"noc": (cx + 2.0, cy),
"sram": (2.5, cy - 1.5),
}
@@ -359,16 +354,21 @@ def _instantiate_cube(
) -> None:
"""Add all cube-internal nodes and edges, including PE instances.
Topology: PE_DMA → NOC → xbar_top/bot → HBM_CTRL.
No per-PE xbar nodes; position-aware XBAR top/bottom replaces chaining.
Topology: explicit router mesh from cube_mesh.yaml (ADR-0019).
Each router is a separate SimPy node. Components attach to routers
based on cube_mesh.yaml attachment lists.
"""
cube_w = cube["geometry"]["cube_mm"]["w"]
cube_h = cube["geometry"]["cube_mm"]["h"]
ox, oy = origin
local_pos = _cube_local_positions(cube_w, cube_h)
clinks = cube["links"]
n_slices = cube["memory_map"]["hbm_slices_per_cube"]
half = n_slices // 2
mm = cube["memory_map"]
# ── Mode branch (ADR-0019) ──
mode = mm.get("hbm_mapping_mode", "n_to_one")
if mode == "one_to_one":
raise NotImplementedError("1:1 mode: ADR-0019 D3")
# ── UCIe ports + connection nodes ──
ucie_cfg = cube["ucie"]
@@ -391,8 +391,8 @@ def _instantiate_cube(
label=f"UCIe-{port} C{ci}",
)
# ── Named components: noc, m_cpu, sram ──
for name in ("noc", "m_cpu", "sram"):
# ── Named components: m_cpu, sram (noc is now explicit routers) ──
for name in ("m_cpu", "sram"):
c = cube["components"][name]
nid = f"{cp}.{name}"
lx, ly = local_pos[name]
@@ -402,49 +402,96 @@ def _instantiate_cube(
label=name.upper().replace("_", " "),
)
# ── xbar_top and xbar_bot (position-aware XBAR) ──
xbar_spec = cube["components"]["xbar"]
for xbar_name, xbar_cfg in [("xbar_top", xbar_spec["top"]),
("xbar_bot", xbar_spec["bottom"])]:
nid = f"{cp}.{xbar_name}"
lx, ly = local_pos[xbar_name]
nodes[nid] = Node(
id=nid, kind=xbar_cfg["kind"], impl=xbar_cfg["impl"],
attrs=xbar_cfg["attrs"], pos_mm=(ox + lx, oy + ly),
label=xbar_name.upper().replace("_", " "),
)
# ── HBM controller slices ──
# ── HBM controller (single node, ADR-0019 D1) ──
hbm_spec = cube["components"]["hbm_ctrl"]
hbm_lx, hbm_ly = local_pos["hbm_ctrl"]
for sl in range(n_slices):
sid = f"{cp}.hbm_ctrl.slice{sl}"
nodes[sid] = Node(
id=sid, kind=hbm_spec["kind"], impl=hbm_spec["impl"],
attrs=hbm_spec["attrs"], pos_mm=(ox + hbm_lx, oy + hbm_ly),
label=f"HBM SLICE{sl}",
hbm_id = f"{cp}.hbm_ctrl"
nodes[hbm_id] = Node(
id=hbm_id, kind=hbm_spec["kind"], impl=hbm_spec["impl"],
attrs=hbm_spec["attrs"], pos_mm=(ox + hbm_lx, oy + hbm_ly),
label="HBM CTRL",
)
# ── Router mesh from cube_mesh.yaml (ADR-0019 D3) ──
routers = mesh_data["routers"]
router_spec = cube["components"]["noc_router"]
router_bw = clinks.get("router_link_bw_gbs", 256.0)
pe_to_router_bw = clinks.get("pe_to_router_bw_gbs", 256.0)
hbm_eff = float(hbm_spec.get("attrs", {}).get("efficiency", 1.0))
hbm_to_router_bw = clinks.get("hbm_to_router_bw_gbs", 256.0) * hbm_eff
sram_to_router_bw = clinks.get("sram_to_router_bw_gbs", 128.0)
ucie_conn_bw = ucie_cfg.get("per_connection_bw_gbs", 128.0)
n_rows = mesh_data["mesh"]["rows"]
n_cols = mesh_data["mesh"]["cols"]
# Create router nodes
for rkey, rval in routers.items():
if rval is None:
continue
rid = f"{cp}.{rkey}"
rx, ry = rval["pos_mm"]
nodes[rid] = Node(
id=rid, kind=router_spec["kind"], impl=router_spec["impl"],
attrs=router_spec["attrs"], pos_mm=(ox + rx, oy + ry),
label=rkey.upper(),
)
# ── Bridges ──
for br in xbar_spec["bridges"]:
bname = br["id"]
nid = f"{cp}.bridge.{bname}"
lx, ly = local_pos[f"bridge.{bname}"]
nodes[nid] = Node(
id=nid, kind=br["kind"], impl=br["impl"],
attrs=br["attrs"], pos_mm=(ox + lx, oy + ly),
label=f"Bridge {bname.upper()}",
)
# Router ↔ router XY mesh edges (adjacent non-null routers)
for r in range(n_rows):
for c in range(n_cols):
rkey = f"r{r}c{c}"
if routers.get(rkey) is None:
continue
src_id = f"{cp}.{rkey}"
src_pos = routers[rkey]["pos_mm"]
# ── PE instances (no per-PE xbar nodes) ──
# Horizontal neighbor (same row, next col)
for nc in range(c + 1, n_cols):
nkey = f"r{r}c{nc}"
if routers.get(nkey) is None:
continue
dst_id = f"{cp}.{nkey}"
dst_pos = routers[nkey]["pos_mm"]
dist = abs(dst_pos[0] - src_pos[0])
edges.append(Edge(
src=src_id, dst=dst_id,
distance_mm=round(dist, 2), bw_gbs=router_bw,
kind="router_mesh",
))
edges.append(Edge(
src=dst_id, dst=src_id,
distance_mm=round(dist, 2), bw_gbs=router_bw,
kind="router_mesh",
))
break # only immediate neighbor
# Vertical neighbor (same col, next row)
for nr in range(r + 1, n_rows):
nkey = f"r{nr}c{c}"
if routers.get(nkey) is None:
continue
dst_id = f"{cp}.{nkey}"
dst_pos = routers[nkey]["pos_mm"]
dist = abs(dst_pos[1] - src_pos[1])
edges.append(Edge(
src=src_id, dst=dst_id,
distance_mm=round(dist, 2), bw_gbs=router_bw,
kind="router_mesh",
))
edges.append(Edge(
src=dst_id, dst=src_id,
distance_mm=round(dist, 2), bw_gbs=router_bw,
kind="router_mesh",
))
break # only immediate neighbor
# ── PE instances ──
corners = cube["pe_layout"]["corners"]
pe_per_corner = cube["pe_layout"]["pe_per_corner"]
corner_pos = _corner_pe_positions(cube_w, cube_h)
pe_tmpl = cube["pe_template"]
pe_links = pe_tmpl["links"]
pe_noc_distances = _compute_pe_noc_distances(
mesh_data, corner_pos, corners, pe_per_corner,
)
pe_idx = 0
for corner in corners:
@@ -465,166 +512,121 @@ def _instantiate_cube(
# PE-internal edges
_add_pe_internal_edges(edges, pp, pe_links)
# PE_DMA → noc (distance auto-computed from PE physical position)
edges.append(Edge(
src=f"{pp}.pe_dma", dst=f"{cp}.noc",
distance_mm=pe_noc_distances.get(pe_idx, 0.0),
bw_gbs=clinks["pe_dma_to_noc_bw_gbs"],
kind="pe_to_noc",
))
# noc → PE_DMA (response delivery, reverse of pe_to_noc)
edges.append(Edge(
src=f"{cp}.noc", dst=f"{pp}.pe_dma",
distance_mm=pe_noc_distances.get(pe_idx, 0.0),
bw_gbs=clinks["pe_dma_to_noc_bw_gbs"],
kind="noc_to_pe",
))
# noc → PE_CPU (command delivery)
edges.append(Edge(
src=f"{cp}.noc", dst=f"{pp}.pe_cpu",
distance_mm=clinks["noc_to_pe_cpu_mm"],
kind="command",
))
# PE_CPU → noc (response delivery, reverse of command)
edges.append(Edge(
src=f"{pp}.pe_cpu", dst=f"{cp}.noc",
distance_mm=clinks["noc_to_pe_cpu_mm"],
kind="pe_response",
))
# noc → PE_MMU (MMU mapping install)
pe_mmu_id = f"{pp}.pe_mmu"
if pe_mmu_id in nodes:
edges.append(Edge(
src=f"{cp}.noc", dst=pe_mmu_id,
distance_mm=clinks.get("noc_to_pe_mmu_mm", 0.0),
kind="command",
))
pe_idx += 1
# ── xbar_top/bot → HBM slices ──
hbm_eff = float(hbm_spec.get("attrs", {}).get("efficiency", 1.0))
hbm_bw = clinks["xbar_to_hbm_bw_gbs"] * hbm_eff
for i in range(half):
edges.append(Edge(
src=f"{cp}.xbar_top", dst=f"{cp}.hbm_ctrl.slice{i}",
distance_mm=clinks["xbar_to_hbm_mm"],
bw_gbs=hbm_bw,
kind="xbar_to_hbm",
))
edges.append(Edge(
src=f"{cp}.hbm_ctrl.slice{i}", dst=f"{cp}.xbar_top",
distance_mm=clinks["xbar_to_hbm_mm"],
bw_gbs=hbm_bw,
kind="hbm_to_xbar",
))
for i in range(half, n_slices):
edges.append(Edge(
src=f"{cp}.xbar_bot", dst=f"{cp}.hbm_ctrl.slice{i}",
distance_mm=clinks["xbar_to_hbm_mm"],
bw_gbs=hbm_bw,
kind="xbar_to_hbm",
))
edges.append(Edge(
src=f"{cp}.hbm_ctrl.slice{i}", dst=f"{cp}.xbar_bot",
distance_mm=clinks["xbar_to_hbm_mm"],
bw_gbs=hbm_bw,
kind="hbm_to_xbar",
))
# ── Component ↔ router edges (based on cube_mesh.yaml attach) ──
for rkey, rval in routers.items():
if rval is None:
continue
rid = f"{cp}.{rkey}"
for item in rval.get("attach", []):
if item.endswith(".dma"):
# PE_DMA ↔ router
pe_prefix = item.rsplit(".", 1)[0]
dma_id = f"{cp}.{pe_prefix}.pe_dma"
if dma_id in nodes:
edges.append(Edge(
src=dma_id, dst=rid,
distance_mm=0.0, bw_gbs=pe_to_router_bw,
kind="pe_to_router",
))
edges.append(Edge(
src=rid, dst=dma_id,
distance_mm=0.0, bw_gbs=pe_to_router_bw,
kind="router_to_pe",
))
elif item.endswith(".cpu"):
# PE_CPU ↔ router (command path)
pe_prefix = item.rsplit(".", 1)[0]
cpu_id = f"{cp}.{pe_prefix}.pe_cpu"
if cpu_id in nodes:
edges.append(Edge(
src=rid, dst=cpu_id,
distance_mm=clinks.get("noc_to_pe_cpu_mm", 0.0),
kind="command",
))
edges.append(Edge(
src=cpu_id, dst=rid,
distance_mm=clinks.get("noc_to_pe_cpu_mm", 0.0),
kind="pe_response",
))
elif item.endswith(".hbm"):
pass # HBM edges handled below (all routers)
elif item == "m_cpu":
# M_CPU ↔ router
mcpu_id = f"{cp}.m_cpu"
edges.append(Edge(
src=mcpu_id, dst=rid,
distance_mm=clinks.get("m_cpu_to_router_mm", 0.0),
kind="command",
))
edges.append(Edge(
src=rid, dst=mcpu_id,
distance_mm=clinks.get("m_cpu_to_router_mm", 0.0),
kind="command",
))
elif item == "sram":
# SRAM ↔ router
sram_id = f"{cp}.sram"
edges.append(Edge(
src=sram_id, dst=rid,
distance_mm=0.0, bw_gbs=sram_to_router_bw,
kind="sram_to_router",
))
edges.append(Edge(
src=rid, dst=sram_id,
distance_mm=0.0, bw_gbs=sram_to_router_bw,
kind="router_to_sram",
))
elif item.startswith("ucie_"):
# UCIe conn ↔ router
# item format: "ucie_{dir}.c{i}" e.g. "ucie_n.c0"
parts = item.split(".")
direction = parts[0].replace("ucie_", "").upper()
conn_num = parts[1].replace("c", "") # "0", "1", etc.
conn_id = f"{cp}.ucie-{direction}.conn{conn_num}"
ucie_id = f"{cp}.ucie-{direction}"
# conn ↔ ucie port
if conn_id in nodes:
edges.append(Edge(
src=ucie_id, dst=conn_id,
distance_mm=0.0, kind="ucie_internal",
))
edges.append(Edge(
src=conn_id, dst=ucie_id,
distance_mm=0.0, kind="ucie_internal",
))
# conn ↔ router
edges.append(Edge(
src=conn_id, dst=rid,
distance_mm=0.0, bw_gbs=ucie_conn_bw,
kind="ucie_conn_to_router",
))
edges.append(Edge(
src=rid, dst=conn_id,
distance_mm=0.0, bw_gbs=ucie_conn_bw,
kind="router_to_ucie_conn",
))
# ── NOC ↔ xbar_top/bot ──
# xbar_top: primary (low routing weight), xbar_bot: secondary (high routing weight
# steers Dijkstra through xbar_top→bridge→xbar_bot for cross-half access)
noc_xbar_bw = clinks.get("noc_to_xbar_bw_gbs", 256.0)
noc_xbar_mm = clinks.get("noc_to_xbar_mm", 0.0)
for xbar_name, rw in [("xbar_top", None), ("xbar_bot", 100.0)]:
# ── HBM_CTRL ↔ all routers (ADR-0019 D1) ──
# High routing weight prevents Dijkstra from using HBM as transit shortcut
for rkey, rval in routers.items():
if rval is None:
continue
rid = f"{cp}.{rkey}"
edges.append(Edge(
src=f"{cp}.noc", dst=f"{cp}.{xbar_name}",
distance_mm=noc_xbar_mm, bw_gbs=noc_xbar_bw,
routing_weight_mm=rw, kind="noc_to_xbar",
src=rid, dst=hbm_id,
distance_mm=0.0, bw_gbs=hbm_to_router_bw,
routing_weight_mm=1000.0,
kind="router_to_hbm",
))
edges.append(Edge(
src=f"{cp}.{xbar_name}", dst=f"{cp}.noc",
distance_mm=noc_xbar_mm, bw_gbs=noc_xbar_bw,
routing_weight_mm=rw, kind="xbar_to_noc",
src=hbm_id, dst=rid,
distance_mm=0.0, bw_gbs=hbm_to_router_bw,
routing_weight_mm=1000.0,
kind="hbm_to_router",
))
# ── Bridge connections: xbar_top ↔ bridge ↔ xbar_bot ──
bridge_mm = clinks.get("xbar_to_bridge_mm", 3.0)
bridge_bw = clinks.get("xbar_to_bridge_bw_gbs", 128.0)
for bname in ("left", "right"):
br_node = f"{cp}.bridge.{bname}"
for xbar_name in ("xbar_top", "xbar_bot"):
edges.append(Edge(
src=f"{cp}.{xbar_name}", dst=br_node,
distance_mm=bridge_mm, bw_gbs=bridge_bw,
kind="xbar_to_bridge",
))
edges.append(Edge(
src=br_node, dst=f"{cp}.{xbar_name}",
distance_mm=bridge_mm, bw_gbs=bridge_bw,
kind="bridge_to_xbar",
))
# ── UCIe ↔ conn ↔ NOC ──
ucie_conn_bw = ucie_cfg.get("per_connection_bw_gbs", 128.0)
for port in ucie_cfg["ports"]:
ucie_id = f"{cp}.ucie-{port}"
for ci in range(ucie_n_conn):
conn_id = f"{cp}.ucie-{port}.conn{ci}"
edges.append(Edge(
src=ucie_id, dst=conn_id,
distance_mm=0.0, kind="ucie_internal",
))
edges.append(Edge(
src=conn_id, dst=ucie_id,
distance_mm=0.0, kind="ucie_internal",
))
edges.append(Edge(
src=conn_id, dst=f"{cp}.noc",
distance_mm=0.0, bw_gbs=ucie_conn_bw,
kind="ucie_conn_to_noc",
))
edges.append(Edge(
src=f"{cp}.noc", dst=conn_id,
distance_mm=0.0, bw_gbs=ucie_conn_bw,
kind="noc_to_ucie_conn",
))
# ── m_cpu ↔ noc (command dispatch) ──
edges.append(Edge(
src=f"{cp}.m_cpu", dst=f"{cp}.noc",
distance_mm=clinks["m_cpu_to_noc_mm"],
kind="command",
))
edges.append(Edge(
src=f"{cp}.noc", dst=f"{cp}.m_cpu",
distance_mm=clinks["m_cpu_to_noc_mm"],
kind="command",
))
# ── noc ↔ sram ──
_noc_sram = clinks["noc_to_sram"]
edges.append(Edge(
src=f"{cp}.noc", dst=f"{cp}.sram",
distance_mm=clinks["noc_to_sram_mm"],
bw_gbs=_noc_sram["per_connection_bw_gbs"],
n_connections=_noc_sram["n_connections"],
kind="noc_to_sram",
))
edges.append(Edge(
src=f"{cp}.sram", dst=f"{cp}.noc",
distance_mm=clinks["noc_to_sram_mm"],
bw_gbs=_noc_sram["per_connection_bw_gbs"],
n_connections=_noc_sram["n_connections"],
kind="noc_to_sram",
))
def _add_pe_internal_edges(edges: list[Edge], pp: str, pe_links: dict) -> None:
"""Add PE-internal edges for a single PE instance."""
@@ -901,8 +903,8 @@ def _build_cube_view(spec: dict) -> ViewGraph:
label=f"UCIe-{port} C{ci}",
)
# Named components (hbm_ctrl as single representative node in view)
for name in ("noc", "m_cpu", "hbm_ctrl", "sram"):
# Named components (hbm_ctrl as single node in view)
for name in ("m_cpu", "hbm_ctrl", "sram"):
c = cube["components"][name]
lx, ly = local_pos.get(name, local_pos.get("hbm_ctrl"))
nodes[name] = Node(
@@ -911,27 +913,15 @@ def _build_cube_view(spec: dict) -> ViewGraph:
label=name.upper().replace("_", " "),
)
# xbar_top, xbar_bot
xbar_spec = cube["components"]["xbar"]
for xbar_name, xbar_cfg in [("xbar_top", xbar_spec["top"]),
("xbar_bot", xbar_spec["bottom"])]:
lx, ly = local_pos[xbar_name]
nodes[xbar_name] = Node(
id=xbar_name, kind=xbar_cfg["kind"], impl=xbar_cfg["impl"],
attrs=xbar_cfg["attrs"], pos_mm=(lx, ly),
label=xbar_name.upper().replace("_", " "),
)
# Bridges
for br in xbar_spec["bridges"]:
bname = br["id"]
bid = f"bridge.{bname}"
lx, ly = local_pos[bid]
nodes[bid] = Node(
id=bid, kind=br["kind"], impl=br["impl"],
attrs=br["attrs"], pos_mm=(lx, ly),
label=f"Bridge {bname.upper()}",
)
# Router mesh representative node (collapsed for view)
router_spec = cube["components"]["noc_router"]
cx = cube_w / 2
cy = cube_h / 2
nodes["router_mesh"] = Node(
id="router_mesh", kind=router_spec["kind"], impl=router_spec["impl"],
attrs=router_spec["attrs"], pos_mm=(cx + 2.0, cy),
label="ROUTER MESH",
)
# PEs as opaque blocks (no per-PE xbar nodes)
corners = cube["pe_layout"]["corners"]
@@ -952,75 +942,62 @@ def _build_cube_view(spec: dict) -> ViewGraph:
attrs={"corner": corner}, pos_mm=(px, py),
label=f"PE{pe_idx}",
)
# PE → noc (distance auto-computed from PE physical position)
# PE ↔ router_mesh (view representation)
pe_to_router_bw = clinks.get("pe_to_router_bw_gbs", 256.0)
view_edges.append(Edge(
src=pid, dst="noc",
src=pid, dst="router_mesh",
distance_mm=pe_noc_distances.get(pe_idx, 0.0),
bw_gbs=clinks["pe_dma_to_noc_bw_gbs"],
kind="pe_to_noc",
bw_gbs=pe_to_router_bw,
kind="pe_to_router",
))
# noc → PE (command delivery)
view_edges.append(Edge(
src="noc", dst=pid,
distance_mm=clinks["noc_to_pe_cpu_mm"],
src="router_mesh", dst=pid,
distance_mm=clinks.get("noc_to_pe_cpu_mm", 0.0),
kind="command",
))
pe_idx += 1
# xbar_top/bot → hbm_ctrl
# router_mesh ↔ hbm_ctrl
hbm_to_router_bw = clinks.get("hbm_to_router_bw_gbs", 256.0)
view_edges.append(Edge(
src="xbar_top", dst="hbm_ctrl",
distance_mm=clinks["xbar_to_hbm_mm"],
bw_gbs=clinks["xbar_to_hbm_bw_gbs"],
kind="xbar_to_hbm",
src="router_mesh", dst="hbm_ctrl",
distance_mm=0.0, bw_gbs=hbm_to_router_bw,
kind="router_to_hbm",
))
view_edges.append(Edge(
src="xbar_bot", dst="hbm_ctrl",
distance_mm=clinks["xbar_to_hbm_mm"],
bw_gbs=clinks["xbar_to_hbm_bw_gbs"],
kind="xbar_to_hbm",
src="hbm_ctrl", dst="router_mesh",
distance_mm=0.0, bw_gbs=hbm_to_router_bw,
kind="hbm_to_router",
))
# noc ↔ xbar_top/bot
noc_xbar_bw = clinks.get("noc_to_xbar_bw_gbs", 256.0)
noc_xbar_mm = clinks.get("noc_to_xbar_mm", 0.0)
for xbar_name in ("xbar_top", "xbar_bot"):
view_edges.append(Edge(
src="noc", dst=xbar_name,
distance_mm=noc_xbar_mm, bw_gbs=noc_xbar_bw,
kind="noc_to_xbar",
))
view_edges.append(Edge(
src=xbar_name, dst="noc",
distance_mm=noc_xbar_mm, bw_gbs=noc_xbar_bw,
kind="xbar_to_noc",
))
# router_mesh ↔ m_cpu
view_edges.append(Edge(
src="m_cpu", dst="router_mesh",
distance_mm=clinks.get("m_cpu_to_router_mm", 0.0),
kind="command",
))
view_edges.append(Edge(
src="router_mesh", dst="m_cpu",
distance_mm=clinks.get("m_cpu_to_router_mm", 0.0),
kind="command",
))
# bridge connections: xbar_top ↔ bridge ↔ xbar_bot
bridge_mm = clinks.get("xbar_to_bridge_mm", 3.0)
bridge_bw = clinks.get("xbar_to_bridge_bw_gbs", 128.0)
for bname in ("left", "right"):
br_id = f"bridge.{bname}"
for xbar_name in ("xbar_top", "xbar_bot"):
view_edges.append(Edge(
src=xbar_name, dst=br_id,
distance_mm=bridge_mm, bw_gbs=bridge_bw,
kind="xbar_to_bridge",
))
view_edges.append(Edge(
src=br_id, dst=xbar_name,
distance_mm=bridge_mm, bw_gbs=bridge_bw,
kind="bridge_to_xbar",
))
# router_mesh ↔ sram
sram_bw = clinks.get("sram_to_router_bw_gbs", 128.0)
view_edges.append(Edge(
src="router_mesh", dst="sram",
distance_mm=0.0, bw_gbs=sram_bw,
kind="router_to_sram",
))
ucie_conn_bw_v = ucie_cfg.get("per_connection_bw_gbs", 128.0)
for port in ucie_cfg["ports"]:
for ci in range(ucie_n_conn):
conn_id = f"ucie-{port}.conn{ci}"
view_edges.append(Edge(
src="noc", dst=conn_id,
src="router_mesh", dst=conn_id,
distance_mm=0.0, bw_gbs=ucie_conn_bw_v,
kind="noc_to_ucie_conn",
kind="router_to_ucie_conn",
))
view_edges.append(Edge(
src=conn_id, dst=f"ucie-{port}",
@@ -1031,40 +1008,11 @@ def _build_cube_view(spec: dict) -> ViewGraph:
distance_mm=0.0, kind="ucie_internal",
))
view_edges.append(Edge(
src=conn_id, dst="noc",
src=conn_id, dst="router_mesh",
distance_mm=0.0, bw_gbs=ucie_conn_bw_v,
kind="ucie_conn_to_noc",
kind="ucie_conn_to_router",
))
# m_cpu ↔ noc
view_edges.append(Edge(
src="m_cpu", dst="noc",
distance_mm=clinks["m_cpu_to_noc_mm"],
kind="command",
))
view_edges.append(Edge(
src="noc", dst="m_cpu",
distance_mm=clinks["m_cpu_to_noc_mm"],
kind="command",
))
# noc ↔ sram
_noc_sram_v = clinks["noc_to_sram"]
view_edges.append(Edge(
src="noc", dst="sram",
distance_mm=clinks["noc_to_sram_mm"],
bw_gbs=_noc_sram_v["per_connection_bw_gbs"],
n_connections=_noc_sram_v["n_connections"],
kind="noc_to_sram",
))
view_edges.append(Edge(
src="sram", dst="noc",
distance_mm=clinks["noc_to_sram_mm"],
bw_gbs=_noc_sram_v["per_connection_bw_gbs"],
n_connections=_noc_sram_v["n_connections"],
kind="noc_to_sram",
))
return ViewGraph(
name="cube", nodes=nodes, edges=view_edges,
width_mm=cube_w, height_mm=cube_h,