Remove xbar/noc remnants, rule-based cube-view connectors
- Delete xbar.py and noc.py (TwoDMeshNocComponent) — unused since router mesh - Remove xbar_v1/noc_2d_mesh_v1 from components.yaml - Fix pe_to_xbar → pe_to_router in routing exclusion set - Fix xbar_to_hbm_bw_gbs → hbm_to_router_bw_gbs in report.py - Update all docstrings/comments referencing xbar/bridge → router mesh - Cube-view connectors: rule-based _connector_points helper - PE↔router: single diagonal line (not chevron) - UCIe N/S: 45°→horizontal→45° - UCIe E/W: 45°→vertical→45° - HBM ports: 45°→horizontal→45° Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,9 +28,6 @@ components:
|
||||
switch_v1: kernbench.components.builtin.forwarding:TransitComponent
|
||||
noc_v1: kernbench.components.builtin.forwarding:TransitComponent
|
||||
ucie_v1: kernbench.components.builtin.forwarding:TransitComponent
|
||||
noc_2d_mesh_v1: kernbench.components.builtin.noc:TwoDMeshNocComponent
|
||||
xbar_v1: kernbench.components.builtin.xbar:PositionAwareXbarComponent
|
||||
|
||||
# IO / Host interface
|
||||
pcie_ep_v1: kernbench.components.builtin.pcie_ep:PcieEpComponent
|
||||
io_cpu_v1: kernbench.components.builtin.io_cpu:IoCpuComponent
|
||||
|
||||
+38
-38
@@ -135,17 +135,14 @@
|
||||
<text x="135" y="138" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r0c0</text>
|
||||
<rect x="119" y="81" width="32" height="16" rx="3" fill="#2d1f3d" stroke="#a855f7" stroke-width="1"/>
|
||||
<text x="135" y="92" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#a855f7">PE0</text>
|
||||
<polyline points="135,127 147,115 147,109 135,97" fill="none" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<line x1="135" y1="127" x2="149" y2="97" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<circle cx="285" cy="135" r="8" fill="#475569" stroke="#64748b" stroke-width="1"/>
|
||||
<text x="285" y="138" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r0c1</text>
|
||||
<rect x="269" y="81" width="32" height="16" rx="3" fill="#2d1f3d" stroke="#a855f7" stroke-width="1"/>
|
||||
<text x="285" y="92" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#a855f7">PE1</text>
|
||||
<polyline points="285,127 297,115 297,109 285,97" fill="none" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<circle cx="435" cy="135" r="8" fill="#475569" stroke="#64748b" stroke-width="1"/>
|
||||
<line x1="285" y1="127" x2="299" y2="97" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<circle cx="435" cy="135" r="8" fill="#334155" stroke="#475569" stroke-width="1"/>
|
||||
<text x="435" y="138" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r0c2</text>
|
||||
<rect x="419" y="81" width="32" height="16" rx="3" fill="#451a03" stroke="#f59e0b" stroke-width="1"/>
|
||||
<text x="435" y="92" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#f59e0b">M_CPU</text>
|
||||
<polyline points="435,127 423,115 423,109 435,97" fill="none" stroke="#f59e0b" stroke-width="1" opacity="0.6"/>
|
||||
<circle cx="585" cy="135" r="8" fill="#334155" stroke="#475569" stroke-width="1"/>
|
||||
<text x="585" y="138" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r0c3</text>
|
||||
<circle cx="685" cy="135" r="8" fill="#475569" stroke="#64748b" stroke-width="1"/>
|
||||
@@ -156,20 +153,23 @@
|
||||
<text x="135" y="263" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r1c0</text>
|
||||
<circle cx="285" cy="260" r="8" fill="#334155" stroke="#475569" stroke-width="1"/>
|
||||
<text x="285" y="263" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r1c1</text>
|
||||
<circle cx="435" cy="260" r="8" fill="#334155" stroke="#475569" stroke-width="1"/>
|
||||
<circle cx="435" cy="260" r="8" fill="#475569" stroke="#64748b" stroke-width="1"/>
|
||||
<text x="435" y="263" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r1c2</text>
|
||||
<rect x="419" y="206" width="32" height="16" rx="3" fill="#451a03" stroke="#f59e0b" stroke-width="1"/>
|
||||
<text x="435" y="217" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#f59e0b">M_CPU</text>
|
||||
<line x1="435" y1="252" x2="449" y2="222" stroke="#f59e0b" stroke-width="1" opacity="0.6"/>
|
||||
<circle cx="585" cy="260" r="8" fill="#334155" stroke="#475569" stroke-width="1"/>
|
||||
<text x="585" y="263" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r1c3</text>
|
||||
<circle cx="685" cy="260" r="8" fill="#475569" stroke="#64748b" stroke-width="1"/>
|
||||
<text x="685" y="263" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r1c4</text>
|
||||
<rect x="669" y="206" width="32" height="16" rx="3" fill="#2d1f3d" stroke="#a855f7" stroke-width="1"/>
|
||||
<text x="685" y="217" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#a855f7">PE2</text>
|
||||
<polyline points="685,252 697,240 697,234 685,222" fill="none" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<line x1="685" y1="252" x2="699" y2="222" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<circle cx="835" cy="260" r="8" fill="#475569" stroke="#64748b" stroke-width="1"/>
|
||||
<text x="835" y="263" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r1c5</text>
|
||||
<rect x="819" y="206" width="32" height="16" rx="3" fill="#2d1f3d" stroke="#a855f7" stroke-width="1"/>
|
||||
<text x="835" y="217" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#a855f7">PE3</text>
|
||||
<polyline points="835,252 847,240 847,234 835,222" fill="none" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<line x1="835" y1="252" x2="849" y2="222" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<circle cx="135" cy="335" r="8" fill="#334155" stroke="#475569" stroke-width="1"/>
|
||||
<text x="135" y="338" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r2c0</text>
|
||||
<circle cx="285" cy="335" r="8" fill="#334155" stroke="#475569" stroke-width="1"/>
|
||||
@@ -182,7 +182,7 @@
|
||||
<text x="135" y="488" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r3c0</text>
|
||||
<rect x="119" y="523" width="32" height="16" rx="3" fill="#1c1917" stroke="#d97706" stroke-width="1"/>
|
||||
<text x="135" y="534" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#d97706">SRAM</text>
|
||||
<polyline points="135,493 123,505 123,511 135,523" fill="none" stroke="#d97706" stroke-width="1" opacity="0.6"/>
|
||||
<line x1="135" y1="493" x2="149" y2="523" stroke="#d97706" stroke-width="1" opacity="0.6"/>
|
||||
<circle cx="285" cy="485" r="8" fill="#334155" stroke="#475569" stroke-width="1"/>
|
||||
<text x="285" y="488" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r3c1</text>
|
||||
<circle cx="685" cy="485" r="8" fill="#334155" stroke="#475569" stroke-width="1"/>
|
||||
@@ -193,12 +193,12 @@
|
||||
<text x="135" y="563" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r4c0</text>
|
||||
<rect x="119" y="598" width="32" height="16" rx="3" fill="#2d1f3d" stroke="#a855f7" stroke-width="1"/>
|
||||
<text x="135" y="609" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#a855f7">PE4</text>
|
||||
<polyline points="135,568 147,580 147,586 135,598" fill="none" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<line x1="135" y1="568" x2="149" y2="598" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<circle cx="285" cy="560" r="8" fill="#475569" stroke="#64748b" stroke-width="1"/>
|
||||
<text x="285" y="563" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r4c1</text>
|
||||
<rect x="269" y="598" width="32" height="16" rx="3" fill="#2d1f3d" stroke="#a855f7" stroke-width="1"/>
|
||||
<text x="285" y="609" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#a855f7">PE5</text>
|
||||
<polyline points="285,568 297,580 297,586 285,598" fill="none" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<line x1="285" y1="568" x2="299" y2="598" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<circle cx="435" cy="560" r="8" fill="#334155" stroke="#475569" stroke-width="1"/>
|
||||
<text x="435" y="563" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r4c2</text>
|
||||
<circle cx="585" cy="560" r="8" fill="#334155" stroke="#475569" stroke-width="1"/>
|
||||
@@ -219,84 +219,84 @@
|
||||
<text x="685" y="688" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r5c4</text>
|
||||
<rect x="669" y="723" width="32" height="16" rx="3" fill="#2d1f3d" stroke="#a855f7" stroke-width="1"/>
|
||||
<text x="685" y="734" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#a855f7">PE6</text>
|
||||
<polyline points="685,693 697,705 697,711 685,723" fill="none" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<line x1="685" y1="693" x2="699" y2="723" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<circle cx="835" cy="685" r="8" fill="#475569" stroke="#64748b" stroke-width="1"/>
|
||||
<text x="835" y="688" text-anchor="middle" font-family="monospace" font-size="6" fill="white">r5c5</text>
|
||||
<rect x="819" y="723" width="32" height="16" rx="3" fill="#2d1f3d" stroke="#a855f7" stroke-width="1"/>
|
||||
<text x="835" y="734" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#a855f7">PE7</text>
|
||||
<polyline points="835,693 847,705 847,711 835,723" fill="none" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<polyline points="135,143 147,155 147,277 324,289" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<line x1="835" y1="693" x2="849" y2="723" stroke="#a855f7" stroke-width="1" opacity="0.6"/>
|
||||
<polyline points="135,143 208,216 251,216 324,289" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<text x="239" y="216" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text>
|
||||
<polyline points="285,143 297,155 297,277 431,289" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<polyline points="285,143 358,216 358,216 431,289" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<text x="368" y="216" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text>
|
||||
<polyline points="685,268 673,280 673,277 539,289" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<polyline points="685,268 674,278 549,278 539,289" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<text x="622" y="278" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text>
|
||||
<polyline points="835,268 823,280 823,277 646,289" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<polyline points="835,268 824,278 657,278 646,289" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<text x="751" y="278" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text>
|
||||
<polyline points="135,552 147,540 147,543 324,531" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<polyline points="135,552 146,542 313,542 324,531" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<text x="239" y="542" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text>
|
||||
<polyline points="285,552 297,540 297,543 431,531" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<polyline points="285,552 296,542 421,542 431,531" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<text x="368" y="542" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text>
|
||||
<polyline points="685,677 673,665 673,543 539,531" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<polyline points="685,677 612,604 612,604 539,531" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<text x="622" y="604" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text>
|
||||
<polyline points="835,677 823,665 823,543 646,531" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<polyline points="835,677 762,604 719,604 646,531" fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" stroke-dasharray="4,3"/>
|
||||
<text x="751" y="604" font-family="monospace" font-size="6" fill="#10b98188">256GB/s</text>
|
||||
<rect x="65" y="360" width="50" height="100" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.9"/>
|
||||
<text x="90" y="357" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-W</text>
|
||||
<rect x="67" y="362" width="46" height="23" rx="2" fill="#818cf8" opacity="0.7"/>
|
||||
<text x="90" y="376" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text>
|
||||
<polyline points="127,135 117,145 123,145 113,374" fill="none" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="127,135 120,142 120,366 113,374" fill="none" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="67" y="386" width="46" height="23" rx="2" fill="#a78bfa" opacity="0.7"/>
|
||||
<text x="90" y="400" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text>
|
||||
<polyline points="127,260 117,270 123,270 113,398" fill="none" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="127,260 120,267 120,390 113,398" fill="none" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="67" y="410" width="46" height="23" rx="2" fill="#c084fc" opacity="0.7"/>
|
||||
<text x="90" y="424" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text>
|
||||
<polyline points="127,560 117,550 123,550 113,422" fill="none" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="127,560 120,553 120,428 113,422" fill="none" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="67" y="434" width="46" height="23" rx="2" fill="#e879f9" opacity="0.7"/>
|
||||
<text x="90" y="448" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text>
|
||||
<polyline points="127,685 117,675 123,675 113,446" fill="none" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="127,685 120,678 120,452 113,446" fill="none" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="435" y="65" width="100" height="50" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.9"/>
|
||||
<text x="485" y="62" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-N</text>
|
||||
<rect x="437" y="67" width="23" height="46" rx="2" fill="#818cf8" opacity="0.7"/>
|
||||
<text x="448" y="93" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text>
|
||||
<polyline points="135,127 145,117 145,123 448,113" fill="none" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="135,127 142,120 442,120 448,113" fill="none" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="461" y="67" width="23" height="46" rx="2" fill="#a78bfa" opacity="0.7"/>
|
||||
<text x="472" y="93" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text>
|
||||
<polyline points="285,127 295,117 295,123 472,113" fill="none" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="285,127 292,120 466,120 472,113" fill="none" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="485" y="67" width="23" height="46" rx="2" fill="#c084fc" opacity="0.7"/>
|
||||
<text x="496" y="93" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text>
|
||||
<polyline points="685,127 675,117 675,123 496,113" fill="none" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="685,127 678,120 504,120 496,113" fill="none" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="509" y="67" width="23" height="46" rx="2" fill="#e879f9" opacity="0.7"/>
|
||||
<text x="520" y="93" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text>
|
||||
<polyline points="835,127 825,117 825,123 520,113" fill="none" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="835,127 828,120 528,120 520,113" fill="none" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="855" y="360" width="50" height="100" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.9"/>
|
||||
<text x="880" y="357" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-E</text>
|
||||
<rect x="857" y="362" width="46" height="23" rx="2" fill="#818cf8" opacity="0.7"/>
|
||||
<text x="880" y="376" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text>
|
||||
<polyline points="843,135 853,145 847,145 857,374" fill="none" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="843,135 850,142 850,367 857,374" fill="none" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="857" y="386" width="46" height="23" rx="2" fill="#a78bfa" opacity="0.7"/>
|
||||
<text x="880" y="400" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text>
|
||||
<polyline points="843,260 853,270 847,270 857,398" fill="none" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="843,260 850,267 850,391 857,398" fill="none" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="857" y="410" width="46" height="23" rx="2" fill="#c084fc" opacity="0.7"/>
|
||||
<text x="880" y="424" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text>
|
||||
<polyline points="843,560 853,550 847,550 857,422" fill="none" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="843,560 850,553 850,428 857,422" fill="none" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="857" y="434" width="46" height="23" rx="2" fill="#e879f9" opacity="0.7"/>
|
||||
<text x="880" y="448" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text>
|
||||
<polyline points="843,685 853,675 847,675 857,446" fill="none" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="843,685 850,678 850,452 857,446" fill="none" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="435" y="705" width="100" height="50" rx="3" fill="#1e1b4b" stroke="#8b5cf6" stroke-width="1.5" opacity="0.9"/>
|
||||
<text x="485" y="702" text-anchor="middle" font-family="monospace" font-size="7" font-weight="bold" fill="#8b5cf6">UCIe-S</text>
|
||||
<rect x="437" y="707" width="23" height="46" rx="2" fill="#818cf8" opacity="0.7"/>
|
||||
<text x="448" y="733" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c0</text>
|
||||
<polyline points="135,693 145,703 145,697 448,707" fill="none" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="135,693 142,700 442,700 448,707" fill="none" stroke="#818cf8" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="461" y="707" width="23" height="46" rx="2" fill="#a78bfa" opacity="0.7"/>
|
||||
<text x="472" y="733" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c1</text>
|
||||
<polyline points="285,693 295,703 295,697 472,707" fill="none" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="285,693 292,700 466,700 472,707" fill="none" stroke="#a78bfa" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="485" y="707" width="23" height="46" rx="2" fill="#c084fc" opacity="0.7"/>
|
||||
<text x="496" y="733" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c2</text>
|
||||
<polyline points="685,693 675,703 675,697 496,707" fill="none" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="685,693 678,700 504,700 496,707" fill="none" stroke="#c084fc" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="509" y="707" width="23" height="46" rx="2" fill="#e879f9" opacity="0.7"/>
|
||||
<text x="520" y="733" text-anchor="middle" font-family="monospace" font-size="5" fill="white">c3</text>
|
||||
<polyline points="835,693 825,703 825,697 520,707" fill="none" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
|
||||
<polyline points="835,693 828,700 528,700 520,707" fill="none" stroke="#e879f9" stroke-width="1" opacity="0.5"/>
|
||||
<rect x="60" y="865" width="10" height="10" rx="2" fill="#3b82f6" stroke="#475569" stroke-width="0.5"/>
|
||||
<text x="74" y="874" font-family="monospace" font-size="8" fill="#94a3b8">PE Router</text>
|
||||
<rect x="147" y="865" width="10" height="10" rx="2" fill="#f59e0b" stroke="#475569" stroke-width="0.5"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
@@ -116,7 +116,7 @@ def _fmt_util(eff: float, bn: float | None) -> str:
|
||||
|
||||
|
||||
def _short_name(node_id: str) -> str:
|
||||
"""Shorten node id: keep last 2 segments to avoid ambiguity (xbar.pe0 vs pe0)."""
|
||||
"""Shorten node id: keep last 2 segments to avoid ambiguity (router.pe0 vs pe0)."""
|
||||
parts = node_id.split(".")
|
||||
return ".".join(parts[-2:]) if len(parts) >= 2 else node_id
|
||||
|
||||
@@ -366,7 +366,7 @@ def run_probe(topology_path: str, case_filter: str | None = None) -> int:
|
||||
|
||||
# --- PE DMA Summary Table ---
|
||||
print()
|
||||
print(f"=== PE DMA Latency (pe_dma -> xbar -> HBM, data={nbytes}B) ===")
|
||||
print(f"=== PE DMA Latency (pe_dma -> router -> HBM, data={nbytes}B) ===")
|
||||
print(f" {'Case':<26} {'Target':<28} {'Actual':>8}"
|
||||
f" {'Ovhd':>6} {'Drain':>6} {'Wire':>5} {'Ovhd%':>6} {'Drain%':>7}"
|
||||
f" {'Eff.BW':>8} {'BN.BW':>8} {'Util%':>6}")
|
||||
|
||||
@@ -137,7 +137,7 @@ def _extract_peaks(spec: dict | None) -> tuple[float, float]:
|
||||
gemm_attrs = comps.get("pe_gemm", {}).get("attrs", {})
|
||||
peak_tflops = float(gemm_attrs.get("peak_tflops_f16", 0.0))
|
||||
cube_links = cube.get("links", {})
|
||||
hbm_bw = float(cube_links.get("xbar_to_hbm_bw_gbs", 0.0))
|
||||
hbm_bw = float(cube_links.get("hbm_to_router_bw_gbs", 0.0))
|
||||
return peak_tflops, hbm_bw
|
||||
|
||||
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Generator
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import simpy
|
||||
|
||||
from kernbench.components.base import ComponentBase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from kernbench.components.context import ComponentContext
|
||||
from kernbench.topology.types import Node
|
||||
|
||||
|
||||
class TwoDMeshNocComponent(ComponentBase):
|
||||
"""2D mesh NOC modeled as a single smart node.
|
||||
|
||||
Latency model:
|
||||
- Traversal latency = Manhattan distance between prev_hop and next_hop
|
||||
node positions, split into XY segments, traversed with pipeline.
|
||||
- overhead_ns (from node.attrs) is added once per traversal.
|
||||
|
||||
Contention model:
|
||||
- Each directed XY segment is a simpy.Resource(capacity=1).
|
||||
- Pipeline: next segment's resource is requested before the current
|
||||
segment's timeout completes, so a free downstream segment is acquired
|
||||
immediately (wormhole-style cut-through).
|
||||
- Two transactions sharing a segment (same row or column band) contend.
|
||||
|
||||
Concurrency:
|
||||
- _worker spawns an independent SimPy process per transaction, so the
|
||||
NOC is never serialized at the node level — only at segment resources.
|
||||
"""
|
||||
|
||||
def __init__(self, node: Node, ctx: ComponentContext | None = None) -> None:
|
||||
super().__init__(node, ctx)
|
||||
self._env: simpy.Environment | None = None
|
||||
self._links: dict[tuple, simpy.Resource] = {}
|
||||
self._x_grid: list[float] = []
|
||||
self._y_grid: list[float] = []
|
||||
|
||||
def start(self, env: simpy.Environment) -> None:
|
||||
self._env = env
|
||||
self._build_grid()
|
||||
super().start(env)
|
||||
|
||||
def run(self, env: simpy.Environment, nbytes: int) -> Generator:
|
||||
yield env.timeout(0)
|
||||
|
||||
# ── Grid construction ────────────────────────────────────────────
|
||||
|
||||
def _build_grid(self) -> None:
|
||||
if not self.ctx:
|
||||
return
|
||||
mesh = self.ctx.spec.get("_mesh") if self.ctx.spec else None
|
||||
if mesh:
|
||||
self._build_grid_from_mesh(mesh)
|
||||
else:
|
||||
self._build_grid_from_positions()
|
||||
|
||||
def _build_grid_from_mesh(self, mesh: dict) -> None:
|
||||
"""Build XY grid from cube_mesh.yaml router positions (authoritative)."""
|
||||
origin_x, origin_y = self._cube_origin()
|
||||
xs: set[float] = set()
|
||||
ys: set[float] = set()
|
||||
for key, router in mesh.get("routers", {}).items():
|
||||
if router is not None:
|
||||
xs.add(round(origin_x + router["pos_mm"][0], 2))
|
||||
ys.add(round(origin_y + router["pos_mm"][1], 2))
|
||||
self._x_grid = sorted(xs)
|
||||
self._y_grid = sorted(ys)
|
||||
|
||||
def _build_grid_from_positions(self) -> None:
|
||||
"""Fallback: infer grid from all node positions in the cube."""
|
||||
cube_prefix = self.node.id.rsplit(".", 1)[0]
|
||||
xs: set[float] = set()
|
||||
ys: set[float] = set()
|
||||
for node_id, pos in self.ctx.positions.items():
|
||||
if node_id.startswith(cube_prefix + ".") and pos is not None:
|
||||
xs.add(round(pos[0], 2))
|
||||
ys.add(round(pos[1], 2))
|
||||
self._x_grid = sorted(xs)
|
||||
self._y_grid = sorted(ys)
|
||||
|
||||
def _cube_origin(self) -> tuple[float, float]:
|
||||
"""Compute absolute origin (top-left) of this cube from cube_id."""
|
||||
parts = self.node.id.split(".")
|
||||
cube_str = [p for p in parts if p.startswith("cube")][0]
|
||||
cube_id = int(cube_str[4:])
|
||||
spec = self.ctx.spec
|
||||
sip_spec = spec.get("sip", {})
|
||||
cube_spec = spec.get("cube", {})
|
||||
mesh_w = sip_spec.get("cube_mesh", {}).get("w", 4)
|
||||
cube_w = cube_spec.get("geometry", {}).get("cube_mm", {}).get("w", 17.0)
|
||||
cube_h = cube_spec.get("geometry", {}).get("cube_mm", {}).get("h", 14.0)
|
||||
seam = sip_spec.get("links", {}).get("inter_cube_mesh", {}).get(
|
||||
"distance_mm_across_seam", 1.0)
|
||||
col = cube_id % mesh_w
|
||||
row = cube_id // mesh_w
|
||||
return (col * (cube_w + seam), row * (cube_h + seam))
|
||||
|
||||
def _get_link(self, key: tuple) -> simpy.Resource:
|
||||
if key not in self._links:
|
||||
assert self._env is not None
|
||||
self._links[key] = simpy.Resource(self._env, capacity=1)
|
||||
return self._links[key]
|
||||
|
||||
# ── Worker ───────────────────────────────────────────────────────
|
||||
|
||||
def _worker(self, env: simpy.Environment) -> Generator:
|
||||
while True:
|
||||
txn: Any = yield self._inbox.get()
|
||||
env.process(self._route(env, txn))
|
||||
|
||||
def _route(self, env: simpy.Environment, txn: Any) -> Generator:
|
||||
prev_hop = txn.path[txn.step - 1] if txn.step > 0 else None
|
||||
next_hop = txn.next_hop
|
||||
overhead_ns = float(self.node.attrs.get("overhead_ns", 0.0))
|
||||
|
||||
links: list[tuple[tuple, float]] = []
|
||||
if prev_hop and next_hop and self.ctx:
|
||||
src_pos = self.ctx.positions.get(prev_hop)
|
||||
dst_pos = self.ctx.positions.get(next_hop)
|
||||
if src_pos and dst_pos:
|
||||
links = self._xy_links(src_pos, dst_pos)
|
||||
|
||||
if links:
|
||||
yield from self._traverse(env, links, overhead_ns)
|
||||
else:
|
||||
yield env.timeout(overhead_ns)
|
||||
|
||||
if next_hop:
|
||||
yield self.out_ports[next_hop].put(txn.advance())
|
||||
else:
|
||||
drain = getattr(txn, "drain_ns", 0.0)
|
||||
if drain > 0:
|
||||
yield env.timeout(drain)
|
||||
txn.done.succeed()
|
||||
|
||||
# ── XY routing and pipelined link traversal ──────────────────────
|
||||
|
||||
def _traverse(
|
||||
self,
|
||||
env: simpy.Environment,
|
||||
links: list[tuple[tuple, float]],
|
||||
overhead_ns: float,
|
||||
) -> Generator:
|
||||
"""Pipeline: request next segment before current timeout finishes."""
|
||||
ns_per_mm = self.ctx.ns_per_mm # type: ignore[union-attr]
|
||||
|
||||
# Acquire first link
|
||||
first_key, _ = links[0]
|
||||
current_resource = self._get_link(first_key)
|
||||
current_req = current_resource.request()
|
||||
yield current_req
|
||||
|
||||
for i, (_, dist_mm) in enumerate(links):
|
||||
# Request next link before current timeout (pipeline)
|
||||
if i + 1 < len(links):
|
||||
next_key, _ = links[i + 1]
|
||||
next_resource = self._get_link(next_key)
|
||||
next_req = next_resource.request()
|
||||
|
||||
yield env.timeout(dist_mm * ns_per_mm + (overhead_ns if i == 0 else 0.0))
|
||||
current_resource.release(current_req)
|
||||
|
||||
if i + 1 < len(links):
|
||||
yield next_req # usually already fulfilled (pipeline)
|
||||
current_resource = next_resource
|
||||
current_req = next_req
|
||||
|
||||
def _xy_links(
|
||||
self,
|
||||
src: tuple[float, float],
|
||||
dst: tuple[float, float],
|
||||
) -> list[tuple[tuple, float]]:
|
||||
"""XY routing: horizontal segment first, then vertical.
|
||||
|
||||
Returns list of (link_key, dist_mm) pairs, where link_key uniquely
|
||||
identifies a directed segment shared across concurrent transactions.
|
||||
"""
|
||||
x0, y0 = src
|
||||
x1, y1 = dst
|
||||
links: list[tuple[tuple, float]] = []
|
||||
|
||||
# Horizontal segment at y≈y0
|
||||
if abs(x0 - x1) > 1e-9:
|
||||
y_band = self._snap(y0, self._y_grid)
|
||||
for xa, xb in self._segments(x0, x1, self._x_grid):
|
||||
d = abs(xb - xa)
|
||||
if d > 1e-9:
|
||||
lo, hi = (xa, xb) if xa < xb else (xb, xa)
|
||||
dir_h = "E" if xb > xa else "W"
|
||||
links.append((("H", round(y_band, 2), round(lo, 2), round(hi, 2), dir_h), d))
|
||||
|
||||
# Vertical segment at x≈x1
|
||||
if abs(y0 - y1) > 1e-9:
|
||||
x_band = self._snap(x1, self._x_grid)
|
||||
for ya, yb in self._segments(y0, y1, self._y_grid):
|
||||
d = abs(yb - ya)
|
||||
if d > 1e-9:
|
||||
lo, hi = (ya, yb) if ya < yb else (yb, ya)
|
||||
dir_v = "S" if yb > ya else "N"
|
||||
links.append((("V", round(x_band, 2), round(lo, 2), round(hi, 2), dir_v), d))
|
||||
|
||||
return links
|
||||
|
||||
@staticmethod
|
||||
def _snap(val: float, grid: list[float]) -> float:
|
||||
if not grid:
|
||||
return val
|
||||
return min(grid, key=lambda g: abs(g - val))
|
||||
|
||||
@staticmethod
|
||||
def _segments(a: float, b: float, grid: list[float]) -> list[tuple[float, float]]:
|
||||
"""Consecutive (p_i, p_{i+1}) pairs covering range [a, b] using grid waypoints."""
|
||||
if abs(a - b) < 1e-9:
|
||||
return []
|
||||
lo, hi = (a, b) if a < b else (b, a)
|
||||
pts = [lo] + [g for g in grid if lo + 1e-9 < g < hi - 1e-9] + [hi]
|
||||
pairs = [(pts[i], pts[i + 1]) for i in range(len(pts) - 1)]
|
||||
if a > b:
|
||||
pairs = [(p2, p1) for p1, p2 in reversed(pairs)]
|
||||
return pairs
|
||||
@@ -96,7 +96,7 @@ class PeDmaComponent(PeEngineBase):
|
||||
request=sub_request, path=path, step=0,
|
||||
nbytes=cmd.nbytes, done=sub_done, drain_ns=drain_ns,
|
||||
)
|
||||
# Send to next hop (path[0] is pe_dma itself, path[1] is xbar)
|
||||
# Send to next hop (path[0] is pe_dma itself, path[1] is router)
|
||||
if len(path) > 1:
|
||||
yield self.out_ports[path[1]].put(sub_txn.advance())
|
||||
# DMA channel released after issue
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
"""Position-aware XBAR component.
|
||||
|
||||
Models crossbar latency as base_overhead_ns + internal_distance * ns_per_mm,
|
||||
where internal_distance is the Manhattan distance between the entry port
|
||||
(PE router attachment) and exit port (HBM slice logical position) within
|
||||
the crossbar matrix.
|
||||
|
||||
PE router positions come from cube_mesh.yaml (via ctx.spec["_mesh"]).
|
||||
HBM slice positions are uniformly distributed across the HBM physical width.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Generator
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import simpy
|
||||
|
||||
from kernbench.components.base import ComponentBase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from kernbench.components.context import ComponentContext
|
||||
from kernbench.topology.types import Node
|
||||
|
||||
|
||||
class PositionAwareXbarComponent(ComponentBase):
|
||||
"""XBAR with position-dependent latency based on PE-to-slice distance.
|
||||
|
||||
Latency = base_overhead_ns + |entry_port_x - exit_port_x| * ns_per_mm
|
||||
|
||||
Entry/exit port X positions are determined from the transaction path:
|
||||
- PE_DMA nodes: router X from cube_mesh.yaml
|
||||
- HBM slices: uniformly distributed across HBM physical width
|
||||
- Bridge nodes: physical X from topology positions
|
||||
- NOC: resolved by scanning path for PE_DMA node
|
||||
"""
|
||||
|
||||
def __init__(self, node: Node, ctx: ComponentContext | None = None) -> None:
|
||||
super().__init__(node, ctx)
|
||||
self._base_overhead_ns = float(node.attrs.get("overhead_ns", 0.0))
|
||||
self._pe_router_xs: dict[str, float] = {}
|
||||
self._slice_xs: dict[str, float] = {}
|
||||
self._bridge_xs: dict[str, float] = {}
|
||||
self._ns_per_mm: float = 0.0
|
||||
|
||||
def start(self, env: simpy.Environment) -> None:
|
||||
self._build_position_map()
|
||||
super().start(env)
|
||||
|
||||
def run(self, env: simpy.Environment, nbytes: int) -> Generator:
|
||||
yield env.timeout(self._base_overhead_ns)
|
||||
|
||||
# ── Position map construction ─────────────────────────────────
|
||||
|
||||
def _build_position_map(self) -> None:
|
||||
if not self.ctx or not self.ctx.spec:
|
||||
return
|
||||
mesh = self.ctx.spec.get("_mesh")
|
||||
if not mesh:
|
||||
return
|
||||
|
||||
self._ns_per_mm = self.ctx.ns_per_mm
|
||||
cube_prefix = self.node.id.rsplit(".", 1)[0]
|
||||
xbar_name = self.node.id.rsplit(".", 1)[1]
|
||||
is_top = xbar_name == "xbar_top"
|
||||
xbar_key = "top" if is_top else "bottom"
|
||||
|
||||
# PE router X positions from mesh attachments
|
||||
routers_list = mesh.get("xbar", {}).get(xbar_key, {}).get("routers", [])
|
||||
for router_id in routers_list:
|
||||
router_data = mesh["routers"].get(router_id)
|
||||
if router_data is None:
|
||||
continue
|
||||
router_x = router_data["pos_mm"][0]
|
||||
for attach in router_data.get("attach", []):
|
||||
if attach.endswith(".dma"):
|
||||
pe_name = attach.split(".")[0]
|
||||
pe_dma_id = f"{cube_prefix}.{pe_name}.pe_dma"
|
||||
self._pe_router_xs[pe_dma_id] = router_x
|
||||
|
||||
# HBM slice X positions: uniformly distributed across HBM width
|
||||
cube_spec = self.ctx.spec.get("cube", {})
|
||||
cube_w = cube_spec.get("geometry", {}).get("cube_mm", {}).get("w", 17.0)
|
||||
hbm_w = cube_spec.get("geometry", {}).get("hbm_mm", {}).get("w", 9.0)
|
||||
n_slices = cube_spec.get("memory_map", {}).get("hbm_slices_per_cube", 8)
|
||||
half = n_slices // 2
|
||||
hbm_left = (cube_w - hbm_w) / 2
|
||||
|
||||
if is_top:
|
||||
slice_range = range(half)
|
||||
else:
|
||||
slice_range = range(half, n_slices)
|
||||
|
||||
n = len(list(slice_range))
|
||||
for i, sl in enumerate(slice_range):
|
||||
if n > 1:
|
||||
x = hbm_left + i * hbm_w / (n - 1)
|
||||
else:
|
||||
x = cube_w / 2
|
||||
self._slice_xs[f"{cube_prefix}.hbm_ctrl.slice{sl}"] = x
|
||||
|
||||
# Bridge X positions from topology positions
|
||||
for node_id, pos in self.ctx.positions.items():
|
||||
if node_id.startswith(cube_prefix + ".bridge.") and pos is not None:
|
||||
origin_x = self._cube_origin_x()
|
||||
self._bridge_xs[node_id] = pos[0] - origin_x
|
||||
|
||||
def _cube_origin_x(self) -> float:
|
||||
"""Compute absolute X origin of this cube."""
|
||||
parts = self.node.id.split(".")
|
||||
cube_str = [p for p in parts if p.startswith("cube")][0]
|
||||
cube_id = int(cube_str[4:])
|
||||
spec = self.ctx.spec
|
||||
sip_spec = spec.get("sip", {})
|
||||
cube_spec = spec.get("cube", {})
|
||||
mesh_w = sip_spec.get("cube_mesh", {}).get("w", 4)
|
||||
cube_w = cube_spec.get("geometry", {}).get("cube_mm", {}).get("w", 17.0)
|
||||
seam = sip_spec.get("links", {}).get("inter_cube_mesh", {}).get(
|
||||
"distance_mm_across_seam", 1.0)
|
||||
col = cube_id % mesh_w
|
||||
return col * (cube_w + seam)
|
||||
|
||||
# ── Worker override ───────────────────────────────────────────
|
||||
|
||||
def _worker(self, env: simpy.Environment) -> Generator:
|
||||
while True:
|
||||
txn: Any = yield self._inbox.get()
|
||||
env.process(self._position_aware_forward(env, txn))
|
||||
|
||||
def _position_aware_forward(
|
||||
self, env: simpy.Environment, txn: Any,
|
||||
) -> Generator:
|
||||
prev_hop = txn.path[txn.step - 1] if txn.step > 0 else None
|
||||
next_hop = txn.next_hop
|
||||
|
||||
overhead = self._base_overhead_ns
|
||||
if prev_hop and next_hop and self._ns_per_mm > 0:
|
||||
entry_x = self._get_port_x(prev_hop, txn.path)
|
||||
exit_x = self._get_port_x(next_hop, txn.path)
|
||||
if entry_x is not None and exit_x is not None:
|
||||
overhead = self._base_overhead_ns + abs(entry_x - exit_x) * self._ns_per_mm
|
||||
|
||||
yield env.timeout(overhead)
|
||||
|
||||
if next_hop:
|
||||
yield self.out_ports[next_hop].put(txn.advance())
|
||||
else:
|
||||
drain = getattr(txn, "drain_ns", 0.0)
|
||||
if drain > 0:
|
||||
yield env.timeout(drain)
|
||||
txn.done.succeed()
|
||||
|
||||
def _get_port_x(self, node_id: str, path: list[str]) -> float | None:
|
||||
"""Resolve the X position of an XBAR port from node context."""
|
||||
# Direct lookup: PE DMA
|
||||
if node_id in self._pe_router_xs:
|
||||
return self._pe_router_xs[node_id]
|
||||
# Direct lookup: HBM slice
|
||||
if node_id in self._slice_xs:
|
||||
return self._slice_xs[node_id]
|
||||
# Direct lookup: bridge
|
||||
if node_id in self._bridge_xs:
|
||||
return self._bridge_xs[node_id]
|
||||
# NOC: scan path for PE DMA node
|
||||
if "noc" in node_id:
|
||||
for p in path:
|
||||
if p in self._pe_router_xs:
|
||||
return self._pe_router_xs[p]
|
||||
return None
|
||||
@@ -81,7 +81,7 @@ class PathRouter:
|
||||
|
||||
# Edge kinds excluded from M_CPU DMA adjacency: prevents routing through
|
||||
# PE-internal pipeline nodes when computing DMA paths.
|
||||
_MCPU_DMA_EXCLUDE = {"pe_internal", "pe_to_xbar"}
|
||||
_MCPU_DMA_EXCLUDE = {"pe_internal", "pe_to_router"}
|
||||
|
||||
_UCIE_KINDS = {"ucie_internal", "ucie_conn_to_router", "router_to_ucie_conn",
|
||||
"ucie_conn_to_noc", "noc_to_ucie_conn", "ucie_mesh",
|
||||
@@ -124,9 +124,9 @@ class PathRouter:
|
||||
return self._run_dijkstra(self._adj_all, m_cpu_id, dst_hbm_id)
|
||||
|
||||
def find_memory_path(self, src: str, dst: str) -> list[str]:
|
||||
"""Direct memory path: pcie_ep → io_noc → cube → xbar → hbm_ctrl.
|
||||
"""Direct memory path: pcie_ep → io_noc → cube → router mesh → hbm_ctrl.
|
||||
|
||||
Uses _adj_mcpu_dma which excludes pe_internal and pe_to_xbar edges,
|
||||
Uses _adj_mcpu_dma which excludes pe_internal and pe_to_router edges,
|
||||
preventing routing through PE pipeline nodes.
|
||||
"""
|
||||
return self._run_dijkstra(self._adj_mcpu_dma, src, dst)
|
||||
|
||||
@@ -19,9 +19,9 @@ class GraphEngine:
|
||||
"""simpy-based discrete-event simulation engine.
|
||||
|
||||
Request routing:
|
||||
MemoryWrite/Read: pcie_ep → io_noc → cube → xbar → hbm_ctrl (m_cpu bypass)
|
||||
MemoryWrite/Read: pcie_ep → io_noc → cube → router mesh → hbm_ctrl (m_cpu bypass)
|
||||
KernelLaunch: pcie_ep → io_noc → io_cpu → io_noc → cube → m_cpu → PE
|
||||
PeDmaMsg: pe_dma → xbar → hbm_ctrl (direct probe)
|
||||
PeDmaMsg: pe_dma → router mesh → hbm_ctrl (direct probe)
|
||||
|
||||
Component implementations are DI-injectable via component_overrides (ADR-0007 D3).
|
||||
"""
|
||||
@@ -261,7 +261,7 @@ class GraphEngine:
|
||||
done.succeed()
|
||||
|
||||
def _process_memory_direct(self, key: str, request: Any, done: simpy.Event):
|
||||
"""Direct memory path: pcie_ep → io_noc → cube → xbar → hbm_ctrl.
|
||||
"""Direct memory path: pcie_ep → io_noc → cube → router mesh → hbm_ctrl.
|
||||
|
||||
MemoryWrite: data flows forward (nbytes on wires), drain at hbm_ctrl terminal.
|
||||
MemoryRead: command flows forward (nbytes=0), hbm_ctrl sends data back on
|
||||
|
||||
@@ -287,7 +287,7 @@ def _generate_probe_d2h(graph, edge_map) -> list[dict]:
|
||||
|
||||
|
||||
def _generate_probe_pe_dma(graph, edge_map) -> list[dict]:
|
||||
"""PE DMA probes: pe_dma → xbar → HBM."""
|
||||
"""PE DMA probes: pe_dma → router mesh → HBM."""
|
||||
from kernbench.policy.address.phyaddr import PhysAddr
|
||||
from kernbench.policy.routing.router import AddressResolver, PathRouter
|
||||
|
||||
|
||||
@@ -385,6 +385,55 @@ def _escape(text: str) -> str:
|
||||
return text.replace("&", "&").replace("<", "<").replace(">", ">")
|
||||
|
||||
|
||||
# ── Connector helper ─────────────────────────────────────────────────
|
||||
|
||||
|
||||
def _connector_points(
|
||||
rx: float, ry: float, cx: float, cy: float
|
||||
) -> str:
|
||||
"""Return SVG polyline points for a rule-based connector.
|
||||
|
||||
Horizontal-dominant (|dx| >= |dy|): 45° → horizontal straight → 45°.
|
||||
Vertical-dominant (|dy| > |dx|): 45° → vertical straight → 45°.
|
||||
Near-equal or tiny distance: single straight line.
|
||||
"""
|
||||
dx = cx - rx
|
||||
dy = cy - ry
|
||||
adx, ady = abs(dx), abs(dy)
|
||||
|
||||
# Trivial distance → single line
|
||||
# Near-45° diagonal for short distances only (e.g. PE↔router)
|
||||
if adx + ady < 4 or (abs(adx - ady) < 4 and adx + ady < 80):
|
||||
return f"{rx:.0f},{ry:.0f} {cx:.0f},{cy:.0f}"
|
||||
|
||||
sx = 1 if dx >= 0 else -1
|
||||
sy = 1 if dy >= 0 else -1
|
||||
|
||||
if adx >= ady:
|
||||
# Horizontal-dominant: stubs handle vertical, straight is horizontal
|
||||
stub = ady / 2
|
||||
if stub < 2:
|
||||
return f"{rx:.0f},{ry:.0f} {cx:.0f},{cy:.0f}"
|
||||
r45x = rx + sx * stub
|
||||
r45y = ry + sy * stub
|
||||
c45x = cx - sx * stub
|
||||
c45y = cy - sy * stub # r45y == c45y (horizontal)
|
||||
else:
|
||||
# Vertical-dominant: stubs handle horizontal, straight is vertical
|
||||
stub = adx / 2
|
||||
if stub < 2:
|
||||
return f"{rx:.0f},{ry:.0f} {cx:.0f},{cy:.0f}"
|
||||
r45x = rx + sx * stub
|
||||
r45y = ry + sy * stub
|
||||
c45x = cx - sx * stub
|
||||
c45y = cy - sy * stub # r45x == c45x (vertical)
|
||||
|
||||
return (
|
||||
f"{rx:.0f},{ry:.0f} {r45x:.0f},{r45y:.0f} "
|
||||
f"{c45x:.0f},{c45y:.0f} {cx:.0f},{cy:.0f}"
|
||||
)
|
||||
|
||||
|
||||
# ── Cube-specific renderer ──────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -637,53 +686,37 @@ 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: router ─45°─ straight ─45°─ component
|
||||
# Connector: rule-based (short → 45° line, long → 45°-straight-45°)
|
||||
sc = style["stroke"]
|
||||
d = 12 # 45° stub length (px)
|
||||
|
||||
# Determine start (router edge) and end (component edge) points
|
||||
bxc = bx + blk_w / 2 # component center x
|
||||
if kind == "mcpu":
|
||||
# Router top → 45° NW stub → vertical → 45° into block bottom
|
||||
rx2, ry2 = px, py - r_size
|
||||
bxc, byc = bx + blk_w / 2, by + blk_h
|
||||
parts.append(
|
||||
f' <polyline points="'
|
||||
f'{rx2:.0f},{ry2:.0f} {rx2 - d:.0f},{ry2 - d:.0f} '
|
||||
f'{rx2 - d:.0f},{byc + d:.0f} {bxc:.0f},{byc:.0f}" '
|
||||
f'fill="none" stroke="{sc}" stroke-width="1" opacity="0.6"/>'
|
||||
)
|
||||
rx0, ry0 = px, py - r_size # router top
|
||||
cx0, cy0 = bxc, by + blk_h # component bottom
|
||||
elif kind == "sram":
|
||||
# Router bottom → 45° SW stub → vertical → 45° into block top
|
||||
rx2, ry2 = px, py + r_size
|
||||
bxc, byc = bx + blk_w / 2, by
|
||||
rx0, ry0 = px, py + r_size # router bottom
|
||||
cx0, cy0 = bxc, by # component top
|
||||
elif is_top:
|
||||
rx0, ry0 = px, py - r_size # router top
|
||||
cx0, cy0 = bx + blk_w / 2 + offset_x, by + blk_h # component bottom
|
||||
else:
|
||||
rx0, ry0 = px, py + r_size # router bottom
|
||||
cx0, cy0 = bx + blk_w / 2 + offset_x, by # component top
|
||||
|
||||
# PE/M_CPU/SRAM directly above/below router (same X):
|
||||
# single diagonal line from router center to component right edge
|
||||
if abs(cx0 - rx0) < 2 and abs(cy0 - ry0) > 4:
|
||||
cx0 = bx + blk_w - 2
|
||||
parts.append(
|
||||
f' <polyline points="'
|
||||
f'{rx2:.0f},{ry2:.0f} {rx2 - d:.0f},{ry2 + d:.0f} '
|
||||
f'{rx2 - d:.0f},{byc - d:.0f} {bxc:.0f},{byc:.0f}" '
|
||||
f'fill="none" stroke="{sc}" stroke-width="1" opacity="0.6"/>'
|
||||
f' <line x1="{rx0:.0f}" y1="{ry0:.0f}" '
|
||||
f'x2="{cx0:.0f}" y2="{cy0:.0f}" '
|
||||
f'stroke="{sc}" stroke-width="1" opacity="0.6"/>'
|
||||
)
|
||||
else:
|
||||
# PE: vertical direction
|
||||
bxc = bx + blk_w / 2 + offset_x
|
||||
if is_top:
|
||||
rx2, ry2 = px, py - r_size # router top
|
||||
byc = by + blk_h # block bottom
|
||||
# 45° stub from router, vertical, 45° into block
|
||||
sx = bxc - px # horizontal shift direction
|
||||
sd = d if sx >= 0 else -d
|
||||
pts = _connector_points(rx0, ry0, cx0, cy0)
|
||||
parts.append(
|
||||
f' <polyline points="'
|
||||
f'{rx2:.0f},{ry2:.0f} {rx2 + sd:.0f},{ry2 - d:.0f} '
|
||||
f'{rx2 + sd:.0f},{byc + d:.0f} {bxc:.0f},{byc:.0f}" '
|
||||
f'fill="none" stroke="{sc}" stroke-width="1" opacity="0.6"/>'
|
||||
)
|
||||
else:
|
||||
rx2, ry2 = px, py + r_size # router bottom
|
||||
byc = by # block top
|
||||
sx = bxc - px
|
||||
sd = d if sx >= 0 else -d
|
||||
parts.append(
|
||||
f' <polyline points="'
|
||||
f'{rx2:.0f},{ry2:.0f} {rx2 + sd:.0f},{ry2 + d:.0f} '
|
||||
f'{rx2 + sd:.0f},{byc - d:.0f} {bxc:.0f},{byc:.0f}" '
|
||||
f' <polyline points="{pts}" '
|
||||
f'fill="none" stroke="{sc}" stroke-width="1" opacity="0.6"/>'
|
||||
)
|
||||
|
||||
@@ -705,23 +738,10 @@ 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° stub from router → vertical → 45° into HBM port
|
||||
d = 12 # stub length
|
||||
sx = tgx - rpx
|
||||
sd = d if sx >= 0 else -d
|
||||
if rpy < hbm_y:
|
||||
# Rule-based connector: router → HBM port group
|
||||
pts = _connector_points(rpx, r_edge_y, tgx, tgy)
|
||||
parts.append(
|
||||
f' <polyline points="'
|
||||
f'{rpx:.0f},{r_edge_y:.0f} {rpx + sd:.0f},{r_edge_y + d:.0f} '
|
||||
f'{rpx + sd:.0f},{tgy - d:.0f} {tgx:.0f},{tgy:.0f}" '
|
||||
f'fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" '
|
||||
f'stroke-dasharray="4,3"/>'
|
||||
)
|
||||
else:
|
||||
parts.append(
|
||||
f' <polyline points="'
|
||||
f'{rpx:.0f},{r_edge_y:.0f} {rpx + sd:.0f},{r_edge_y - d:.0f} '
|
||||
f'{rpx + sd:.0f},{tgy + d:.0f} {tgx:.0f},{tgy:.0f}" '
|
||||
f' <polyline points="{pts}" '
|
||||
f'fill="none" stroke="#10b981" stroke-width="1.5" opacity="0.6" '
|
||||
f'stroke-dasharray="4,3"/>'
|
||||
)
|
||||
@@ -818,51 +838,25 @@ def _render_cube_view_svg(view: ViewGraph, spec: dict) -> str:
|
||||
f'{conn}</text>'
|
||||
)
|
||||
|
||||
# Connector: router ─45°stub─ straight ─45°stub─ UCIe port
|
||||
# Connector: rule-based router → UCIe port
|
||||
rpx, rpy = mm2px(crx, cry)
|
||||
d = 10
|
||||
if direction == "N":
|
||||
rx, ry = rpx, rpy - r_size
|
||||
tx, ty = lx, cy_box + ch
|
||||
sx = tx - rx
|
||||
sd = d if sx >= 0 else -d
|
||||
parts.append(
|
||||
f' <polyline points="'
|
||||
f'{rx:.0f},{ry:.0f} {rx + sd:.0f},{ry - d:.0f} '
|
||||
f'{rx + sd:.0f},{ty + d:.0f} {tx:.0f},{ty:.0f}" '
|
||||
f'fill="none" stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
|
||||
)
|
||||
elif direction == "S":
|
||||
rx, ry = rpx, rpy + r_size
|
||||
tx, ty = lx, cy_box
|
||||
sx = tx - rx
|
||||
sd = d if sx >= 0 else -d
|
||||
parts.append(
|
||||
f' <polyline points="'
|
||||
f'{rx:.0f},{ry:.0f} {rx + sd:.0f},{ry + d:.0f} '
|
||||
f'{rx + sd:.0f},{ty - d:.0f} {tx:.0f},{ty:.0f}" '
|
||||
f'fill="none" stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
|
||||
)
|
||||
elif direction == "W":
|
||||
rx, ry = rpx - r_size, rpy
|
||||
tx, ty = cx + cw, cy_box + ch / 2
|
||||
sy = ty - ry
|
||||
sd = d if sy >= 0 else -d
|
||||
parts.append(
|
||||
f' <polyline points="'
|
||||
f'{rx:.0f},{ry:.0f} {rx - d:.0f},{ry + sd:.0f} '
|
||||
f'{tx + d:.0f},{ry + sd:.0f} {tx:.0f},{ty:.0f}" '
|
||||
f'fill="none" stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
|
||||
)
|
||||
elif direction == "E":
|
||||
rx, ry = rpx + r_size, rpy
|
||||
tx, ty = cx, cy_box + ch / 2
|
||||
sy = ty - ry
|
||||
sd = d if sy >= 0 else -d
|
||||
else:
|
||||
continue
|
||||
pts = _connector_points(rx, ry, tx, ty)
|
||||
parts.append(
|
||||
f' <polyline points="'
|
||||
f'{rx:.0f},{ry:.0f} {rx + d:.0f},{ry + sd:.0f} '
|
||||
f'{tx - d:.0f},{ry + sd:.0f} {tx:.0f},{ty:.0f}" '
|
||||
f' <polyline points="{pts}" '
|
||||
f'fill="none" stroke="{c_color}" stroke-width="1" opacity="0.5"/>'
|
||||
)
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ def _hbm_pa(pe_id: int = 0) -> int:
|
||||
|
||||
|
||||
def _node(impl: str, overhead_ns: float = 0.0) -> Node:
|
||||
return Node(id="test", kind="xbar", impl=impl, attrs={"overhead_ns": overhead_ns}, pos_mm=None)
|
||||
return Node(id="test", kind="noc_router", impl=impl, attrs={"overhead_ns": overhead_ns}, pos_mm=None)
|
||||
|
||||
|
||||
# ── 1. unknown impl → error ──────────────────────────────────────────
|
||||
@@ -55,7 +55,7 @@ def test_registry_unknown_impl_raises_error():
|
||||
|
||||
def test_transit_component_yields_overhead_ns():
|
||||
"""TransitComponent.run() yields exactly node.attrs['overhead_ns'] ns."""
|
||||
node = _node("xbar_v1", overhead_ns=3.0)
|
||||
node = _node("forwarding_v1", overhead_ns=3.0)
|
||||
comp = TransitComponent(node)
|
||||
env = simpy.Environment()
|
||||
|
||||
@@ -119,10 +119,9 @@ def test_engine_component_model_latency():
|
||||
"""MemoryRead D2H latency for local cube0 (4096B).
|
||||
|
||||
Bypass path (m_cpu bypass): pcie_ep → io_noc → conn → io_ucie → cube_ucie
|
||||
→ conn → noc → xbar_top → hbm_ctrl.slice0
|
||||
→ conn → router mesh → hbm_ctrl
|
||||
|
||||
Path goes through xbar_top (overhead_ns=2.0) instead of per-PE xbar.
|
||||
Latency must be positive and reasonable.
|
||||
Path goes through router mesh. Latency must be positive and reasonable.
|
||||
"""
|
||||
graph = _graph()
|
||||
engine = GraphEngine(graph)
|
||||
@@ -134,7 +133,6 @@ def test_engine_component_model_latency():
|
||||
h = engine.submit(msg)
|
||||
engine.wait(h)
|
||||
_, trace = engine.get_completion(h)
|
||||
# Verify positive latency; exact value depends on path through xbar_top
|
||||
assert trace["total_ns"] > 0
|
||||
|
||||
|
||||
|
||||
+8
-11
@@ -1,18 +1,15 @@
|
||||
"""Tests for #5+#6 CUBE NOC Router Mesh + Position-Aware XBAR.
|
||||
|
||||
Phase 1 verification: all tests FAIL until Phase 2 implements production code.
|
||||
"""Tests for CUBE NOC Explicit Router Mesh (ADR-0019).
|
||||
|
||||
Key changes verified:
|
||||
- Single NOC node per cube with internal router mesh simulation
|
||||
- Auto-layout generates cube_mesh.yaml (6x6 grid for n_connections=4)
|
||||
- Position-aware XBAR (top/bottom) replaces per-PE xbar chaining
|
||||
- Explicit router nodes per cube from cube_mesh.yaml (6×6 grid)
|
||||
- Auto-layout generates cube_mesh.yaml with PE/UCIe/M_CPU/SRAM attachments
|
||||
- Mesh file caching with source_hash change detection
|
||||
- Path routing: PE_DMA → NOC → XBAR_top/bot → HBM_CTRL
|
||||
- Path routing: PE_DMA → router mesh → HBM_CTRL
|
||||
|
||||
Latency invariant after refactor:
|
||||
Local HBM: PE_DMA → Router(overhead) → XBAR → HBM_CTRL
|
||||
Cross-row: PE_DMA → Router → mesh traverse → Router → XBAR → bridge → XBAR → HBM_CTRL
|
||||
Cross-cube: PE_DMA → Router → mesh → UCIe → ... → mesh → XBAR → HBM_CTRL
|
||||
Latency invariant:
|
||||
Local HBM: PE_DMA → Router(overhead) → HBM_CTRL
|
||||
Cross-row: PE_DMA → Router → mesh hops → Router → HBM_CTRL
|
||||
Cross-cube: PE_DMA → Router → mesh → UCIe → ... → mesh → HBM_CTRL
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -24,7 +24,6 @@ from kernbench.components.builtin import (
|
||||
IoCpuComponent,
|
||||
MCpuComponent,
|
||||
PcieEpComponent,
|
||||
PositionAwareXbarComponent,
|
||||
SramComponent,
|
||||
TransitComponent,
|
||||
)
|
||||
@@ -232,7 +231,6 @@ def test_m_cpu_terminal_no_ctx_completes():
|
||||
("forwarding_v1", TransitComponent),
|
||||
("noc_v1", TransitComponent),
|
||||
("ucie_v1", TransitComponent),
|
||||
("xbar_v1", PositionAwareXbarComponent),
|
||||
("pcie_ep_v1", PcieEpComponent),
|
||||
("io_cpu_v1", IoCpuComponent),
|
||||
("m_cpu_v1", MCpuComponent),
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
"""Tests for H2D writes and PE DMA probe latency invariants.
|
||||
|
||||
H2D tests use MemoryWriteMsg (pcie_ep → io_cpu → m_cpu → hbm_ctrl → response).
|
||||
PE DMA tests use PeDmaMsg (direct pe_dma → xbar → hbm_ctrl injection).
|
||||
PE DMA tests use PeDmaMsg (direct pe_dma → router mesh → hbm_ctrl injection).
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
@@ -118,7 +118,7 @@ def test_h2d_local_cube_cut_through():
|
||||
"""H2D to local cube with cut-through should be < 50ns for 4096B.
|
||||
|
||||
Full command path: pcie_ep → io_cpu → ucie → noc → m_cpu
|
||||
DMA: m_cpu → noc → xbar → hbm_ctrl (drain once at terminal)
|
||||
DMA: m_cpu → router mesh → hbm_ctrl (drain once at terminal)
|
||||
Plus response path back.
|
||||
With store-and-forward each hop would serialize; cut-through keeps it low.
|
||||
"""
|
||||
@@ -205,7 +205,7 @@ def test_pe_dma_local_bottleneck_hbm():
|
||||
|
||||
|
||||
def test_pe_dma_same_half_bottleneck_hbm():
|
||||
"""PE DMA pe0→slice1 (same half via xbar_top): bottleneck = HBM effective BW."""
|
||||
"""PE DMA pe0→pe1 HBM (same row via router mesh): bottleneck = HBM effective BW."""
|
||||
bn = _pe_dma_bottleneck(src_cube=0, src_pe=0, dst_pe=1)
|
||||
expected = _hbm_effective_bw()
|
||||
assert bn == expected, f"Same-half PE DMA bottleneck {bn}, expected {expected}"
|
||||
|
||||
@@ -158,9 +158,9 @@ def test_pe_dma_to_router():
|
||||
def test_command_path_m_cpu_router_pe_cpu():
|
||||
es = _edge_set(_graph())
|
||||
cp = "sip0.cube0"
|
||||
# m_cpu <-> r0c2 (bidirectional command)
|
||||
assert (f"{cp}.m_cpu", f"{cp}.r0c2") in es
|
||||
assert (f"{cp}.r0c2", f"{cp}.m_cpu") in es
|
||||
# m_cpu <-> r1c2 (bidirectional command)
|
||||
assert (f"{cp}.m_cpu", f"{cp}.r1c2") in es
|
||||
assert (f"{cp}.r1c2", f"{cp}.m_cpu") in es
|
||||
# router -> pe_cpu for each PE (command kind)
|
||||
assert (f"{cp}.r0c0", f"{cp}.pe0.pe_cpu") in es
|
||||
assert (f"{cp}.r5c5", f"{cp}.pe7.pe_cpu") in es
|
||||
@@ -416,8 +416,8 @@ def test_cube_view_hbm_router():
|
||||
|
||||
|
||||
def test_cube_view_m_cpu_router():
|
||||
"""Cube view: m_cpu connects to its router r0c2."""
|
||||
"""Cube view: m_cpu connects to its router r1c2."""
|
||||
v = _graph().cube_view
|
||||
ves = {(e.src, e.dst) for e in v.edges}
|
||||
assert ("m_cpu", "r0c2") in ves
|
||||
assert ("r0c2", "m_cpu") in ves
|
||||
assert ("m_cpu", "r1c2") in ves
|
||||
assert ("r1c2", "m_cpu") in ves
|
||||
|
||||
+2
-2
@@ -55,7 +55,7 @@ cube:
|
||||
ucie_mm: { size: 2.0 }
|
||||
|
||||
pe_layout:
|
||||
corners: [NW, NE, SW, SE] # N corners → xbar top row; S corners → xbar bottom row
|
||||
corners: [NW, NE, SW, SE] # N corners → top PE rows; S corners → bottom PE rows
|
||||
pe_per_corner: 2 # total PEs per cube: 4 * 2 = 8
|
||||
|
||||
pe_template:
|
||||
@@ -97,7 +97,7 @@ cube:
|
||||
|
||||
# Physical placement of non-PE components (mm coordinates)
|
||||
placement:
|
||||
m_cpu: { pos_mm: [7.5, 2.0] } # top center area, near UCIe-N
|
||||
m_cpu: { pos_mm: [7.5, 3.0] } # top center, below UCIe-N
|
||||
sram: { pos_mm: [1.5, 9.0] } # left side, below HBM zone
|
||||
|
||||
ucie:
|
||||
|
||||
Reference in New Issue
Block a user