learning_gem5 part1_02 创建简单的配置脚本

本教程章节将指导您如何为 gem5 设置一个简单的模拟脚本并首次运行 gem5。假设您已完成教程的第一章,并已成功构建了 gem5,生成了可执行文件 build/ALL/gem5.opt

我们的配置脚本将模拟一个非常简单的系统。我们将只有一个简单的 CPU 核心。这个 CPU 核心将连接到一个系统级的内存总线。我们还将有一个单独的 DDR3 内存通道,也连接到内存总线。

gem5 配置脚本

gem5 二进制文件接受一个 Python 脚本作为参数,该脚本用于设置和执行模拟。在此脚本中,您需要创建要模拟的系统,创建系统的所有组件,并指定系统组件的所有参数。然后,您可以从脚本开始模拟。

gem5 附带了许多示例配置脚本,位于 configs/examples 中。对于 gem5 初学者来说,最相关的脚本位于 configs/examples/gem5-library。这些脚本旨在与 gem5 标准库一起使用,该库提供了可以连接在一起形成完整系统的组件。

关于 SimObjects 的说明

gem5 的模块化设计围绕 SimObject 类型构建。模拟系统中的大多数组件都是 SimObjects:CPU、缓存、内存控制器、总线等。gem5 将这些对象从它们的 C++ 实现导出到 python。因此,从 python 配置脚本中,您可以创建任何 SimObject,设置其参数,并指定 SimObjects 之间的交互。

有关更多信息,请参阅 SimObject 详细信息。

为 gem5 v24.1 设置配置脚本

注意:本节内容取自 2024 gem5 bootcamp 的第 1 部分第 2 节。bootcamp 的幻灯片可以在这里找到[slides].

让我们首先创建一个新的配置文件并打开它:

bash 复制代码
mkdir configs/tutorial/part1/
touch configs/tutorial/part1/simple.py

这只是一个普通的 python 文件,将由 gem5 可执行文件中的嵌入式 python 执行。因此,您可以使用 python 中可用的任何特性和库。

要设置一个基本的配置脚本,我们可以从添加导入开始:

python 复制代码
from gem5.prebuilt.demo.x86_demo_board import X86DemoBoard
from gem5.resources.resource import obtain_resource
from gem5.simulate.simulator import Simulator

接下来,向您的脚本添加一个板卡:

python 复制代码
board = X86DemoBoard()

X86DemoBoard 是一个预构建的板卡,不需要进一步配置,可以按原样用作完整系统。但是,不建议在研究中使用。

源代码可以在 gem5 存储库的 src/python/gem5/prebuilt/demo/x86_demo_board.py 中找到。

它具有以下属性:

  • 3GiB DualChannelDDR4_2400 内存

  • 使用 gem5 TIMING 模型的 2 核处理器

  • 具有 64 KiB 数据和指令 L1 缓存以及 8MiB 共享 L2 缓存,即,定义了私有 L1 、共享 L2 缓存层次结构。

从 gem5 v24.1 开始,X86DemoBoard 可以支持 SE(系统模拟)和 FS(全系统)模拟。

接下来,让我们设置要在板卡上运行的工作负载:

python 复制代码
board.set_workload(
    obtain_resource("x86-ubuntu-24.04-boot-no-systemd")
)

obtain_resource 函数下载工作负载和资源。对于 x86-ubuntu-24.04-boot-no-systemd,它会下载一个磁盘映像和内核,并设置默认参数。

该工作负载启动没有 systemd 的 Ubuntu。工作负载中有三个退出事件,模拟可以在每个退出事件处退出或执行其他操作。要更改退出事件的行为,我们需要设置一个退出事件处理程序。

但是,在此示例中,我们只运行 200 亿个 tick(即 20 毫秒)的模拟:

python 复制代码
sim = Simulator(board)
sim.run(20_000_000_000) # 200 亿 tick 或 20 毫秒

设置配置脚本后,要运行模拟,请使用以下命令:

bash 复制代码
./build/ALL/gem5.opt configs/tutorial/part1/simple.py

如果您使用预构建的 gem5 二进制文件,请使用以下命令:

bash 复制代码
gem5 configs/tutorial/part1/simple.py

输出应类似于以下内容:

复制代码
gem5 Simulator System.  https://www.gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 version 24.1.0.0
gem5 compiled Dec 13 2024 14:59:49
gem5 started Dec 16 2024 13:07:46
gem5 executing on amarillo, pid 543078
command line: ./build/ALL/gem5.opt gem5-dev/testing-website-tutorial/tutorial/part1/simple.py

warn: The X86DemoBoard is solely for demonstration purposes. This board is not known to be be representative of any real-world system. Use with caution.
info: Using default config
warn: Max ticks has already been set prior to setting it through the run call. In these cases the max ticks set through the `run` function is used
Global frequency set at 1000000000000 ticks per second
warn: board.workload.acpi_description_table_pointer.rsdt adopting orphan SimObject param 'entries'
src/mem/dram_interface.cc:690: warn: DRAM device capacity (16384 Mbytes) does not match the address range assigned (2048 Mbytes)
src/mem/dram_interface.cc:690: warn: DRAM device capacity (16384 Mbytes) does not match the address range assigned (2048 Mbytes)
src/sim/kernel_workload.cc:46: info: kernel located at: /home/bees/.cache/gem5/x86-linux-kernel-5.4.0-105-generic
      0: board.pc.south_bridge.cmos.rtc: Real-time clock set to Sun Jan  1 00:00:00 2012
board.pc.com_1.device: Listening for connections on port 3467
src/base/statistics.hh:279: warn: One of the stats is a legacy stat. Legacy stat is a stat that does not belong to any statistics::Group. Legacy stat is deprecated.
src/dev/intel_8254_timer.cc:128: warn: Reading current count from inactive timer.
board.remote_gdb: Listening for connections on port 7003
src/sim/simulate.cc:199: info: Entering event queue @ 0.  Starting simulation...
build/ALL/arch/x86/generated/exec-ns.cc.inc:27: warn: instruction 'fninit' unimplemented

为 gem5 v21.0 设置配置脚本

创建配置文件

让我们首先创建一个新的配置文件并打开它:

bash 复制代码
mkdir configs/tutorial/part1/
touch configs/tutorial/part1/simple.py

这只是一个普通的 python 文件,将由 gem5 可执行文件之中嵌入的 python 执行。因此,您可以使用 python 中可用的任何特性和库。

接下来,我们将创建第一个 SimObject:我们要模拟的系统。System 对象将是我们模拟系统中所有其他对象的父对象。System 对象包含许多功能性的(非时序级别的)信息,如物理内存范围、根时钟域、根电压域、内核(在全系统模拟中)等。要创建系统 SimObject,我们只需像普通的 python 类一样实例化它:

python 复制代码
system = System()

现在我们有了要模拟的系统的引用,让我们设置系统上的时钟。我们首先必须创建一个时钟域。然后我们可以在该域上设置时钟频率。在 SimObject 上设置参数与在 python 中设置对象的成员完全相同,因此我们可以简单地将时钟设置为 1 GHz,例如。最后,我们必须为此时钟域指定一个电压域。由于我们现在不关心系统功耗,我们将只使用电压域的默认选项。

python 复制代码
system.clk_domain = SrcClockDomain()
system.clk_domain.clock = '1GHz'
system.clk_domain.voltage_domain = VoltageDomain()

一旦我们有了一个系统,让我们设置内存的模拟方式。我们将对内存模拟使用时序模式。除了特殊情况(如快速前进和从检查点恢复)外,您几乎总是会对内存模拟使用时序模式。我们还将设置一个大小为 512 MB 的单个内存范围,这是一个非常小的系统。请注意,在 python 配置脚本中,每当需要大小时,您可以用常见的表达和单位来指定该大小,如 '512MB'。类似地,对于时间,您可以使用时间单位(例如,'5ns')。这些将分别自动转换为公共表示形式。

python 复制代码
system.mem_mode = 'timing'
system.mem_ranges = [AddrRange('512MB')]

现在,我们可以创建一个 CPU。我们将从 gem5 中用于 X86 ISA 的最简单的基于时序的 CPU X86TimingSimpleCPU 开始。此 CPU 模型在每个指令执行时单周期执行,除了内存请求,它们流经内存系统。要创建 CPU,您只需实例化该对象:

python 复制代码
system.cpu = X86TimingSimpleCPU()

如果我们想使用 RISCV ISA,我们可以使用 RiscvTimingSimpleCPU,或者如果我们想使用 ARM ISA,我们可以使用 ArmTimingSimpleCPU。但是,在本练习中,我们将继续使用 X86 ISA。

接下来,我们将创建系统级内存总线:

python 复制代码
system.membus = SystemXBar()

现在我们有了内存总线,让我们将 CPU 上的缓存端口连接到它。在这种情况下,由于我们要模拟的系统没有任何缓存,我们将把 I-cache 和 D-cache 端口直接连接到 membus。在此示例系统中,我们没有缓存。

python 复制代码
system.cpu.icache_port = system.membus.cpu_side_ports
system.cpu.dcache_port = system.membus.cpu_side_ports

关于 gem5 端口的说明

为了将内存系统组件连接在一起,gem5 使用端口抽象。每个内存对象可以有两种端口:请求端口和响应端口。请求从请求端口发送到响应端口,响应从响应端口发送到请求端口。连接端口时,必须将请求端口连接到响应端口。

在 python 配置文件中连接端口很容易。您可以简单地将请求端口设置为等于响应端口,它们就会被连接。例如:

python 复制代码
system.cpu.icache_port = system.l1_cache.cpu_side

在此示例中,cpu 的 icache_port 是一个请求端口,而缓存的 cpu_side 是一个响应端口。请求端口和响应端口可以在 = 的任一侧,并且将建立相同的连接。建立连接后,请求者可以向响应者发送请求。在幕后有很多魔法在进行以建立连接,其细节对大多数用户来说并不重要。

gem5 Python 配置中两个端口 = 的另一个显著魔法是,允许一侧有一个端口,另一侧有一个端口数组。例如:

python 复制代码
system.cpu.icache_port = system.membus.cpu_side_ports

在此示例中,cpu 的 icache_port 是一个请求端口,而 membus 的 cpu_side_ports 是一个响应端口数组。在这种情况下,会在 cpu_side_ports 上生成一个新的响应端口,并且这个新创建的端口将连接到请求端口。

我们将在 MemObject 章节中更详细地讨论端口和 MemObject。

接下来,我们需要连接一些其他端口以确保我们的系统能够正常运行。我们需要在 CPU 上创建一个 I/O 控制器并将其连接到内存总线。此外,我们需要将系统中的一个特殊端口连接到 membus。此端口是一个仅功能性的端口,允许系统读取和写入内存。

将 PIO 和中断端口连接到内存总线是 x86 特定的要求。其他 ISA(例如 ARM)不需要这 3 个额外的行。

python 复制代码
system.cpu.createInterruptController()
system.cpu.interrupts[0].pio = system.membus.mem_side_ports
system.cpu.interrupts[0].int_requestor = system.membus.cpu_side_ports
system.cpu.interrupts[0].int_responder = system.membus.mem_side_ports

system.system_port = system.membus.cpu_side_ports

接下来,我们需要创建一个内存控制器并将其连接到 membus。对于这个系统,我们将使用一个简单的 DDR3 控制器,它将负责我们系统的整个内存范围。

python 复制代码
system.mem_ctrl = MemCtrl()
system.mem_ctrl.dram = DDR3_1600_8x8()
system.mem_ctrl.dram.range = system.mem_ranges[0]
system.mem_ctrl.port = system.membus.mem_side_ports

在完成这些最终连接之后,我们已经完成了模拟系统的实例化!我们的系统应该如下图所示。

一个没有缓存的简单系统配置。

接下来,我们需要设置我们希望 CPU 执行的进程。由于我们在系统调用模拟模式(SE 模式)下执行,我们将只是将 CPU 指向已编译的可执行文件。我们将执行一个简单的 "Hello world" 程序。已经有一个随 gem5 一起提供的已编译程序,所以我们将使用它。您可以指定任何为 x86 构建并已静态编译的应用程序。

全系统模拟 vs 系统调用模拟

gem5 可以在两种不同的模式下运行,称为"系统调用模拟"和"全系统"或 SE 和 FS 模式。在全系统模式下(稍后在 full-system-part 中介绍),gem5 模拟整个硬件系统并运行未修改的内核。全系统模式类似于运行虚拟机。

另一方面,系统调用模拟模式不模拟系统中的所有设备,而是专注于模拟 CPU 和内存系统。系统调用模拟更容易配置,因为您不需要实例化真实系统中所需的所有硬件设备。但是,系统调用模拟只模拟 Linux 系统调用,因此只模拟用户模式代码。

如果您的研究问题不需要对操作系统进行建模,并且您希望获得额外的性能,则应使用 SE 模式。但是,如果您需要对系统进行高保真建模,或者操作系统交互(如页表遍历)很重要,那么您应该使用 FS 模式。

首先,我们必须创建进程(另一个 SimObject)。然后我们将进程的命令设置为我们想要运行的命令。这是一个类似于 argv 的列表,可执行文件位于第一个位置,可执行文件的参数位于列表的其余部分。然后我们将 CPU 设置为使用该进程作为其工作负载,最后在 CPU 中创建功能执行上下文。

python 复制代码
binary = 'tests/test-progs/hello/bin/x86/linux/hello'

# 适用于 gem5 V21 及更高版本
system.workload = SEWorkload.init_compatible(binary)

process = Process()
process.cmd = [binary]
system.cpu.workload = process
system.cpu.createThreads()

我们需要做的最后一件事是实例化系统并开始执行。首先,我们创建 Root 对象。然后我们实例化模拟。实例化过程会遍历我们在 python 中创建的所有 SimObjects 并创建相应的 C++ 对象。

请注意,您不必实例化 python 类然后显式地将参数指定为成员变量。您也可以将参数作为命名参数传递,如下面的 Root 对象。

python 复制代码
root = Root(full_system = False, system = system)
m5.instantiate()

最后,我们可以启动实际的模拟!另外请注意,gem5 现在使用 Python 3 风格的 print 函数,因此 print 不再是语句,必须作为函数调用。

python 复制代码
print("Beginning simulation!")
exit_event = m5.simulate()

一旦模拟完成,我们可以检查系统的状态。

python 复制代码
print('Exiting @ tick {} because {}'
      .format(m5.curTick(), exit_event.getCause()))

运行 gem5

现在我们已经创建了一个简单的模拟脚本(完整版本可以在 gem5 代码库的 configs/learning_gem5/part1/simple.py 中找到),我们准备运行 gem5。gem5 可以接受许多参数,但只需要一个位置参数,即模拟脚本。因此,我们可以简单地从 gem5 根目录运行 gem5,如下所示:

bash 复制代码
build/ALL/gem5.opt configs/tutorial/part1/simple.py

输出应为:

复制代码
gem5 Simulator System.  http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.

gem5 version 21.0.0.0
gem5 compiled May 17 2021 18:05:59
gem5 started May 17 2021 22:05:20
gem5 executing on amarillo, pid 75197
command line: build/X86/gem5.opt configs/tutorial/part1/simple.py

Global frequency set at 1000000000000 ticks per second
warn: No dot file generated. Please install pydot to generate the dot file and pdf.
warn: DRAM device capacity (8192 Mbytes) does not match the address range assigned (512 Mbytes)
0: system.remote_gdb: listening for remote gdb on port 7005
Beginning simulation!
info: Entering event queue @ 0.  Starting simulation...
Hello world!
Exiting @ tick 490394000 because exiting with last active thread context

可以更改配置文件中的参数,结果应该会不同。例如,如果您将系统时钟加倍,模拟应该会更快完成。或者,如果您将 DDR 控制器更改为 DDR4,性能应该会更好。

此外,您可以将 CPU 模型更改为 X86MinorCPU 以模拟顺序 CPU,或更改为 X86O3CPU 以模拟乱序 CPU。但是,请注意 X86O3CPU 目前无法与 simple.py 一起工作,因为 X86O3CPU 需要一个具有独立指令和数据缓存的系统(X86O3CPU 可以与下一节中的配置一起工作)。

所有 gem5 BaseCPU 的命名格式为 {ISA}{Type}CPU。因此,如果我们想要一个 RISCV Minor CPU,我们会使用 RiscvMinorCPU

有效的 ISA 有:

  • Riscv

  • Arm

  • X86

  • Sparc

  • Power

  • Mips

CPU 类型有:

  • AtomicSimpleCPU

  • O3CPU

  • TimingSimpleCPu

  • KvmCPU

  • MinorCPU

接下来,我们将在配置文件中添加缓存以模拟更复杂的系统。

bash 复制代码
https://github.com/gem5/website/blob/stable/_pages/documentation/learning_gem5/part1/part1_2_simple_config.md
相关推荐
Eloudy10 小时前
learning_gem5 part1_01 构建 gem5
gem5
Eloudy6 个月前
业界宽松内存模型的不统一而导致的软件问题, gcc, linux kernel, JVM
java·linux·jvm·arch·gem5
yz_弘毅道远10 个月前
笔记1月5
笔记·gem5·计算机体系架构
zhanzhan01091 年前
ubantu20.04安装gem5
大数据·elasticsearch·搜索引擎·系统架构·gem5
叶卡捷琳堡2 年前
Ubuntu20.04搭建gem5并运行helloworld
python·ubuntu·体系结构·gem5
yz_弘毅道远2 年前
gem5 garnet 合成流量: packet注入流程
gem5·计算机体系架构
空空72 年前
【Linux】编译Linux内核
linux·服务器·ubuntu·gem5