gem5 MultiCore Memory System
Gem5 Version:
v25.1.0.0
gem5 多核互联主要分成两条路径: 分别采用 Classic 与 Ruby 两种 memory system
Classicmemory system:
每个 core 的 cache hierarchy 最终通过一个或多个共享crossbar/bus接到 memory side。这里的互联核心对象通常是SystemXBar和L2XBar。Rubymemory system:
每个 core 并不是直接挂到共享 bus 上,而是先绑定到对应的Ruby controller和RubySequencer,再由network和topology将这些 controller 连接起来。
连接关系如下:
Classic:CPU -> cache hierarchy -> XBar -> memoryRuby:CPU -> RubySequencer/controller -> network/topology -> directory/memory controller
Classic memory system 的多核互联机制
Classic memory system 的 interconnect 主要由 BaseXBar 的具体实现承担。最常见的是:
SystemXBar: 系统级共享 interconnect,连接 caches、memory controllers、I/O。L2XBar: 较靠近 core side 的局部 interconnect,通常用于把多个 L1 cache 汇聚到 shared L2,或者作为单核 private L2 前端的局部连接点
在 stdlib 的 cache hierarchy 里,多核通常不是直接“核与核相连”,而是各个 core 的 cache hierarchy 汇到共享 XBar
因此,多核之间的共享路径体现为“共享 interconnect + 共享下层 cache/memory”
结构一: private L1 + shared SystemXBar
最简单的 Classic 多核结构是每个 core 有 private L1I 和 L1D,但它们的 mem_side 都接到同一个 SystemXBar。
1 | core0 -> L1I/L1D \ |
这张图对应的是最直接的 Classic shared interconnect 形式。所有 cores 的 private L1 后端都汇入同一个 SystemXBar,因此这个 SystemXBar 是主要 shared point,也是多核共享访问路径上的核心仲裁点
关键代码:src/python/gem5/components/cachehierarchies/classic/private_l1_cache_hierarchy.py
关键逻辑:
_get_default_membus()创建默认的SystemXBar(width=64)incorporate_cache()中,按board.get_processor().get_num_cores()为每个 core 创建 privateL1I/L1D- 对每个 core:
cpu.connect_icache(...)cpu.connect_dcache(...)self.l1icaches[i].mem_side = self.membus.cpu_side_portsself.l1dcaches[i].mem_side = self.membus.cpu_side_ports
结构二: private L1 + shared L2 + SystemXBar
另一种常见结构是所有 cores 的 private L1 先接到一个共享 L2XBar,再通过 shared L2Cache 接到 SystemXBar。
1 | core0 -> private L1 \ |
这张图里有两个关键 shared point: shared L2XBar 和 shared L2Cache。
相比上一种结构,它把多个 cores 的流量先在更靠近 CPU side 的 shared L2 层级汇聚,再进入系统级 SystemXBar。
关键代码:src/python/gem5/components/cachehierarchies/classic/private_l1_shared_l2_cache_hierarchy.py
关键逻辑:
- 创建默认
SystemXBar - 按 core 数量创建 private
L1I/L1D - 创建一个共享
L2XBar和一个共享L2Cache - 每个 core 的 L1 cache 都接到
self.l2bus.cpu_side_ports self.l2bus.mem_side_ports = self.l2cache.cpu_sideself.membus.cpu_side_ports = self.l2cache.mem_side
结构三: private L1 + private L2 + shared SystemXBar
还有一种结构是每个 core 都有自己的 L2XBar 和 private L2Cache,但各个 L2 的后端仍并到同一个 SystemXBar。
1 | core0 -> L1I/L1D -> L2XBar_0 -> private L2_0 --\ |
这个结构把每个 core 的上层 cache hierarchy 尽量本地化,shared point 被下推到系统级 SystemXBar。因此,core 之间不会共享 L2,但仍通过同一个 system interconnect 访问更远端的 memory system。
关键代码:src/python/gem5/components/cachehierarchies/classic/private_l1_private_l2_cache_hierarchy.py
关键逻辑:
- 创建默认
SystemXBar - 按 core 数量创建
self.l2buses = [L2XBar() ...] - 对每个 core:
- 创建 private
L2Cache - 再在其下创建 private
L1I和L1D self.l2buses[i].mem_side_ports = l2_node.cache.cpu_sideself.membus.cpu_side_ports = l2_node.cache.mem_side
- 创建 private
core 数限制
在 stdlib 里,core 通常来自 processor 对象:
src/python/gem5/components/processors/abstract_processor.pysrc/python/gem5/components/processors/simple_processor.py
其中:
SimpleProcessor会按照num_cores直接创建SimpleCore列表。- cache hierarchy 则按
board.get_processor().get_num_cores()循环创建 cache 和连接。
4. Ruby memory system 的多核互联机制
Ruby 的设计思路与 Classic 不同。它并不是让 CPU 直接接共享 bus,而是引入一套更显式的 memory system 组件:
RubySequencer- protocol-specific
controller networktopology
在 Ruby 中,CPU 的 memory access 会先进对应的 RubySequencer/controller,之后消息通过 Ruby network 在多个 controller 之间传递。这里的“互联拓扑”主要由 network + topology 决定,而不是 SystemXBar。
Ruby 的主要入口文件是: configs/ruby/Ruby.py
关键流程:
create_system()创建RubySystem- 通过
Network.create_network()创建 network 对象 - 根据当前编译的 protocol 调用
configs/ruby/<protocol>.py的create_system() - 由 protocol 脚本返回:
cpu_sequencersdir_cntrlstopology
- 再调用
topology.makeTopology(...)将 controllers 具体连接成网络
Ruby 的 network 与 topology
network 选项定义在: configs/network/Network.py
默认值:
--topology=Crossbar--network=simple
其中,
network:
选择底层网络实现,如simple或garnettopology:
决定 controllers 和 routers 如何连接,如Crossbar、Pt2Pt、Mesh_XY
protocol 将 cores 变成 network nodes
以 MESI_Two_Level 为例: configs/ruby/MESI_Two_Level.py
关键逻辑:
- 对每个
options.num_cpus:- 创建
L1I/L1Dcache - 创建
MESI_Two_Level_L1Cache_Controller - 创建
RubySequencer
- 创建
- 每个 controller 的 request/response
MessageBuffer都接到:ruby_system.network.in_portruby_system.network.out_port
- 再创建 shared
L2 controller、directory controller、DMA controller - 最后把所有 controllers 组成
all_cntrls - 调用
create_topology(all_cntrls, options)
在 Ruby 中:
- CPU 先接
RubySequencer RubySequencer挂在 protocol-specificcontroller上- controller 再通过 message buffers 连接到
Ruby network
MOESI_CMP_directory 的结构与此类似:configs/ruby/MOESI_CMP_directory.py
CHI 的互联机制
CHI 是 Ruby 里更接近片上网络组织方式的一条路径,结构比 MESI_Two_Level 更明确地区分 node 类型:
RNFHNFSNFRNIMN
1 | CPU0 -> RNF0 --\ |
这张图强调的是 CHI 的 node type 分层,而不是某一种固定物理 router 排布。RNF 代表 CPU side request node,HNF 代表 home node / LLC slice,SNF 代表 memory side node,RNI 代表 I/O 或 DMA 入口,整体通过一张 NoC fabric 互联。
关键代码: configs/ruby/CHI.py
关键逻辑:
- 先检查
num_dirs、num_l3caches等约束 - 按
options.num_cpus生成RNF - 生成
HNF、SNF、DMARNI、I/ORNI - 设置 downstream destination
- 根据
options.topology决定用哪些 nodes 去创建 topology
Ruby 下的具体 topology
Crossbar
关键代码: configs/topologies/Crossbar.py
机制:
- 为每个 controller 建一个 router
- 再额外建一个 central
xbarrouter - 每个 controller 通过
ExtLink接到自己的 router - 每个 router 再通过
IntLink双向连接到 centralxbar
1 | CPU0 -> RubySequencer0 -> L1 controller0 -> router0 --\ |
这里的 shared point 是中心 xbar router。与 Classic 的 shared SystemXBar 类似,它也是集中式结构,但运行语义是 Ruby network 上的 message transfer,而不是普通 port 直接连线。
Pt2Pt
关键代码: configs/topologies/Pt2Pt.py
机制:
- 每个 controller 一个 router
- 每个 router 与其它所有 routers 全互连
- 因此 internal link 数量是
O(N^2)
1 | CPU0 -> seq0 -> controller0 -> router0 |
Pt2Pt 没有单一中心节点,所有 routers 彼此直接互联。它的优点是路径直观,缺点是 router 和 link 数量增长很快,因此在 node 数量上去后会明显变重。
这种 topology 在 node 数量增大时会迅速膨胀,因此虽然没有源码层面的硬上限,但实际可扩展性受限。
Mesh_XY
关键代码: configs/topologies/Mesh_XY.py
机制:
num_routers = options.num_cpusnum_rows = options.mesh_rows- 按
num_rows x num_columns构建二维 mesh - controller 通过
ExtLink均匀分布到 routers - router 之间建立 East/West/North/South
IntLink - link
weight用于实现XY routing
1 | R(0,0) ---- R(0,1) ---- R(0,2) |
在这个 topology 中,shared point 不再是单个中心节点,而是整个 mesh fabric。controller 通过 ExtLink 分布到不同 routers 上,消息按照 XY routing 穿过 mesh 到达目标 controller。
Mesh_XY 是 Ruby 中更接近典型 NoC 的多核互联形式。
Ruby 的 core 数约束
实际约束主要来自 protocol 和 topology
包括:
Mesh_XY:
要求mesh_rows > 0,且num_columns * num_rows == num_routersMESI_Three_Level/MESI_Three_Level_HTM:
要求options.num_cpus % options.num_clusters == 0MOESI_AMD_Base:
要求options.num_cpus为偶数CHI:
要求num_dirs >= 1、num_l3caches >= 1
Ruby 术语
Ruby memory system:
gem5 中基于 message passing 的 memory system。CPU 不直接连共享 bus,而是通过RubySequencer和 protocol-specificcontroller接入network。RubySequencer:
CPU side 的 Ruby 入口,负责把 CPU 的 memory access 转成 Ruby protocol 能处理的请求。controller:
Ruby protocol 中的控制节点,例如L1 controller、L2 controller、directory controller、DMA controller。这些 controller 是 topology 连接的基本对象。network:
Ruby 底层网络实现,例如simple或garnet。它定义链路、router、buffer 等基础通信机制。topology:
controller 和 router 的连接方式,例如Crossbar、Pt2Pt、Mesh_XY。它决定 message 在网络中如何穿行。MessageBuffer:
Ruby controller 与 network 之间传递 request/response/unblock 等消息的缓冲与端口对象。
CHI 相关术语
CHI:
Ruby 中一种更偏向 NoC/SoC 组织方式的 protocol 路径,节点类型划分更明确。RNF:Request Node Functional。CPU side request node,通常承载 core 相关的请求入口。HNF:Home Node Functional。通常对应 home node 与 LLC slice,是请求路由和 home 语义的核心节点。SNF:Subordinate Node Functional。通常对应 main memory side 或其它下游 memory node。RNI:Request Node I/O。I/O 或 DMA 一类 non-CPU requester 的入口节点。MN:Misc Node。承载某些系统级 CHI 功能的附加节点。NoC fabric:
不是某个单独类名,而是对整张 on-chip interconnect 网络的概括性称呼