【NoC基础 1-5】

第2课:网络拓扑

🎯 本课目标

深入理解NoC中的核心拓扑结构(Mesh, Torus, Butterfly),掌握拓扑评估指标,能根据应用需求选择合适拓扑。

1. 拓扑结构概述

网络拓扑定义了NoC中路由器节点之间的物理连接方式。拓扑是NoC设计的第一决策——它决定了网络的延迟、吞吐量、面积和功耗的上界。常见的NoC拓扑分为直接网络和间接网络两大类。

常见NoC拓扑分类 ┌─────────────────────────────────┐ │ 直接网络(Direct) │ │ 每个节点既是终端也是路由器 │ │ ├── Mesh (网格) │ │ ├── Torus (环面) │ │ └── Tree (树形) │ └─────────────────────────────────┘ ┌─────────────────────────────────┐ │ 间接网络(Indirect) │ │ 终端与路由器分离 │ │ ├── Butterfly (蝴蝶) │ │ ├── Clos (克洛斯) │ │ └── Fat Tree (胖树) │ └─────────────────────────────────┘

2. Mesh拓扑详解

Mesh是最常用的NoC拓扑,节点排列成二维网格,每个内部节点与上下左右四个邻居相连。Mesh拓扑的规整性使其非常适合芯片的二维平面布局。

4×4 Mesh 拓扑 (0,0)──(1,0)──(2,0)──(3,0) │ │ │ │ (0,1)──(1,1)──(2,1)──(3,1) │ │ │ │ (0,2)──(1,2)──(2,2)──(3,2) │ │ │ │ (0,3)──(1,3)──(2,3)──(3,3) 特点: 节点度4(内),3(边),2(角) 直径=2(k-1), 对分带宽=k, 链路数=2k(k-1)

2.1 Mesh的数学分析

对于k×k的Mesh:节点数N=k²,链路数L=2k(k-1),直径D=2(k-1)=2(√N-1),平均跳数H≈2k/3=2√N/3,对分带宽B=k=√N。这些指标决定了Mesh网络的基本性能特征。

Mesh的关键优势是布局友好:每个路由器只与物理相邻的路由器连接,布线长度均匀且可预测,非常适合ASIC/SoC的二维平面布图。

3. Torus拓扑

Torus在Mesh基础上增加环绕连接——同一行/列的首尾节点相连,消除了Mesh的边缘不均匀性。所有节点度数相同(均为4),直径减半,对分带宽翻倍。

4×4 Torus 拓扑 (环绕连接) (0,0)══(1,0)══(2,0)══(3,0) ║ │ │ ║ (0,1)──(1,1)──(2,1)──(3,1) │ │ │ │ (0,2)──(1,2)──(2,2)──(3,2) ║ │ │ ║ (0,3)══(1,3)══(2,3)══(3,3) ══ ║ = 环绕连接 直径=k, 对分带宽=2k 缺点: 环绕链路布线长

4. Butterfly拓扑

Butterfly是间接网络拓扑,终端节点只连接到第一级和最后一级路由器。具有对数级直径O(logN)和恒定节点度,但路径唯一——无绕行能力。

8节点 Butterfly (log₂8=2级) 终端 级0 级1 终端 P0 ───┤SW0 ├───┤SW4 ├─── P0' P1 ───┤ ├───┤ ├─── P1' P2 ───┤SW1 ├───┤SW5 ├─── P2' P3 ───┤ ├───┤ ├─── P3' P4 ───┤SW2 ├───┤SW6 ├─── P4' P5 ───┤ ├───┤ ├─── P5' P6 ───┤SW3 ├───┤SW7 ├─── P6' P7 ───┤ ├───┤ ├─── P7'

5. 拓扑评估指标对比

指标MeshTorusButterflyFat Tree
直径O(√N)O(√N)O(logN)O(logN)
对分带宽O(√N)O(√N)O(N)O(N)
节点度2-442-4变化
链路数O(N)O(N)O(NlogN)O(NlogN)
布线复杂度
布局友好度★★★★★★★★★★★★★★

6. Verilog实现:Mesh和Torus拓扑

// Mesh拓扑连接模块 - 自动生成路由器间互连
module mesh_topology #(
    parameter MESH_X = 4,
    parameter MESH_Y = 4,
    parameter DATA_WIDTH = 32,
    parameter VC_NUM = 2
)(
    input  logic clk,
    input  logic rst_n
);
    // 水平方向互连信号
    logic [DATA_WIDTH-1:0] east_data  [0:MESH_Y-1][0:MESH_X-1];
    logic                  east_valid [0:MESH_Y-1][0:MESH_X-1];
    logic                  east_ready [0:MESH_Y-1][0:MESH_X-1];
    logic [DATA_WIDTH-1:0] west_data  [0:MESH_Y-1][0:MESH_X-1];
    logic                  west_valid [0:MESH_Y-1][0:MESH_X-1];
    logic                  west_ready [0:MESH_Y-1][0:MESH_X-1];
    // 垂直方向互连信号
    logic [DATA_WIDTH-1:0] north_data [0:MESH_Y-1][0:MESH_X-1];
    logic                  north_valid[0:MESH_Y-1][0:MESH_X-1];
    logic                  north_ready[0:MESH_Y-1][0:MESH_X-1];
    logic [DATA_WIDTH-1:0] south_data [0:MESH_Y-1][0:MESH_X-1];
    logic                  south_valid[0:MESH_Y-1][0:MESH_X-1];
    logic                  south_ready[0:MESH_Y-1][0:MESH_X-1];

    genvar row, col;
    generate
        for (row = 0; row < MESH_Y; row++) begin : gen_row
            for (col = 0; col < MESH_X; col++) begin : gen_col
                if (col < MESH_X - 1) begin : gen_east
                    assign west_data[row][col+1]  = east_data[row][col];
                    assign west_valid[row][col+1] = east_valid[row][col];
                    assign east_ready[row][col]   = west_ready[row][col+1];
                end else begin : gen_east_edge
                    assign east_ready[row][col] = 1'b1;
                end
                if (row > 0) begin : gen_north
                    assign south_data[row-1][col]  = north_data[row][col];
                    assign south_valid[row-1][col] = north_valid[row][col];
                    assign north_ready[row][col]   = south_ready[row-1][col];
                end else begin : gen_north_edge
                    assign north_ready[row][col] = 1'b1;
                end
            end
        end
    endgenerate
endmodule

6.2 Torus环绕连接

// Torus拓扑 - 在Mesh基础上增加环绕连接
module torus_topology #(
    parameter MESH_X = 4,
    parameter MESH_Y = 4,
    parameter DATA_WIDTH = 32
)(
    input  logic clk,
    input  logic rst_n
);
    logic [DATA_WIDTH-1:0] east_data  [0:MESH_Y-1][0:MESH_X-1];
    logic                  east_valid [0:MESH_Y-1][0:MESH_X-1];
    logic                  east_ready [0:MESH_Y-1][0:MESH_X-1];
    logic [DATA_WIDTH-1:0] west_data  [0:MESH_Y-1][0:MESH_X-1];
    logic                  west_valid [0:MESH_Y-1][0:MESH_X-1];
    logic                  west_ready [0:MESH_Y-1][0:MESH_X-1];
    logic [DATA_WIDTH-1:0] north_data [0:MESH_Y-1][0:MESH_X-1];
    logic                  north_valid[0:MESH_Y-1][0:MESH_X-1];
    logic                  north_ready[0:MESH_Y-1][0:MESH_X-1];
    logic [DATA_WIDTH-1:0] south_data [0:MESH_Y-1][0:MESH_X-1];
    logic                  south_valid[0:MESH_Y-1][0:MESH_X-1];
    logic                  south_ready[0:MESH_Y-1][0:MESH_X-1];

    genvar row, col;
    generate
        for (row = 0; row < MESH_Y; row++) begin : gen_row
            for (col = 0; col < MESH_X; col++) begin : gen_col
                if (col < MESH_X - 1) begin : gen_east
                    assign west_data[row][col+1]  = east_data[row][col];
                    assign west_valid[row][col+1] = east_valid[row][col];
                    assign east_ready[row][col]   = west_ready[row][col+1];
                end else begin : gen_east_wrap
                    assign west_data[row][0]      = east_data[row][col];
                    assign west_valid[row][0]     = east_valid[row][col];
                    assign east_ready[row][col]   = west_ready[row][0];
                end
                if (row > 0) begin : gen_north
                    assign south_data[row-1][col]  = north_data[row][col];
                    assign south_valid[row-1][col] = north_valid[row][col];
                    assign north_ready[row][col]   = south_ready[row-1][col];
                end else begin : gen_north_wrap
                    assign south_data[MESH_Y-1][col]  = north_data[row][col];
                    assign south_valid[MESH_Y-1][col] = north_valid[row][col];
                    assign north_ready[row][col]      = south_ready[MESH_Y-1][col];
                end
            end
        end
    endgenerate
endmodule

✅Verilator验证通过

Mesh和Torus拓扑连接逻辑均通过Verilator语法验证。

7. 拓扑选择决策树

💡 拓扑选择指南

核数≤16 → Mesh足够,简单高效

核数16-64 → Mesh或Torus,Torus对分带宽更优

核数>64 → 考虑Fat Tree或层次化拓扑

需要低延迟 → Butterfly/Fat Tree(对数跳数)

需要容错 → Mesh/Torus(多条路径可绕行)

面积受限 → Mesh(布线最规整)

8. 练习

📝 课后练习

练习1:计算8×8 Mesh和8×8 Torus的直径、对分带宽和平均跳数。

练习2:实现Butterfly拓扑的Verilog连接模块。

练习3:分析3D Mesh相比2D Mesh的优势和布线挑战。

🏆 成就解锁:拓扑架构师

你已掌握NoC的核心拓扑结构,可以评估和选择合适的网络拓扑!

8. 拓扑的物理实现考量

拓扑的选择不仅取决于逻辑性能指标,还深受物理实现约束的影响。在芯片的二维平面上,不同拓扑的布线难度和面积开销差异巨大。

8.1 Mesh的布局优势

Mesh拓扑的最大优势是物理规整性:每个路由器只与物理相邻的路由器连接,所有链路长度基本相同(约100-500μm),布线可预测。这简化了时序收敛和信号完整性分析。

实际芯片中,Mesh路由器与处理核心交替排列,形成规整的"棋盘"布局:

Mesh NoC在芯片上的物理布局 ┌─────┬─────┬─────┬─────┐ │Core │ R0 │Core │ R1 │ │ 0 │ │ 1 │ │ ├─────┼─────┼─────┼─────┤ │ R2 │Core │ R3 │Core │ │ │ 2 │ │ 3 │ ├─────┼─────┼─────┼─────┤ │Core │ R4 │Core │ R5 │ │ 4 │ │ 5 │ │ ├─────┼─────┼─────┼─────┤ │ R6 │Core │ R7 │Core │ │ │ 6 │ │ 7 │ └─────┴─────┴─────┴─────┘ Router面积约0.01-0.05mm² 链路长约200-800μm

8.2 Torus的布线挑战

Torus的环绕链路需要跨越整个芯片的长度,可能达到2-5mm。这导致:①延迟不均匀(环绕链路比本地链路慢5-10倍);②需要多级中继器;③功耗增加(长线驱动)。解决方案包括折叠布局和Express Cube。

8.3 异构拓扑

实际SoC中,不同区域的带宽需求不同。例如CPU簇需要高带宽,而I/O区域只需低带宽。异构拓扑允许不同区域使用不同配置:

9. 拓扑的未来趋势

随着芯片规模继续增长,NoC拓扑也在演进:

◀ 上一课 📖 目录 下一课 ▶