GEM5教程--gem5开始之旅(一)

Vanora ·
更新时间:2024-11-15
· 839 次阅读

GEM5教程--gem5开始之旅(一)一、建立GEM51、GEM5的环境要求2、获取GEM5源代码3、第一个GEM5的建立二、创建一个简单的配置脚本1、GEM5的配置文件2、创建一个配置文件3、运行GEM54、总结GEM5系列教程索引

GEM5模拟器是一个用于计算机系统结构研究的模块化平台,包含系统级别的结构以及处理器的微体系结构。读者若想详细的了解,请查看其官方文档GEM5文档

读者如果想要入门GEM5的话,可以参考Learning_GEM5这个网站,这里面有较为详细的教程,可以带读者从入门到精通。小编我对GEM5的入门学习也是从这个Learning_GEM5这个网站学习的,接下来的系列教程,小编我将结合网站的教程以及自己的理解来向读者介绍GEM5。

一、建立GEM5

这一部分将详细的介绍GEM5编译环境的搭建以及GEM5的建立。

1、GEM5的环境要求

(1)本教程是在Ubuntu上运行GEM5的哟

(2)在安装编译GEM5之前,GEM5对系统环境也有要求哟,读者要在GEM5安装之前,将一些要求的依赖环境安装好,例如:Git gcc4.8+ Scons python2.7+ protibuf2.7+等等,如下就是安装依赖环境的所有命令:

sudo apt-get install build-essential sudo apt-get install git sudo apt-get install m4 sudo apt-get install scons sudo apt-get install zlib1g zlib1g-dev sudo apt-get install libprotobuf-dev protobuf-compiler sudo apt-get install libprotoc-dev sudo apt-get install libgoogle-perftools-dev sudo apt-get install python-dev python python-protobuf

在安装这些依赖环境的时候,小编建议可以分别一个一个安装,这样的话安装完之后,可以查看是否安装成功并查看其版本。确定如上依赖环境全部安装完全之后,就可以进行下一步操作了。

2、获取GEM5源代码 git clone https://gem5.googlesource.com/public/gem5

读者应该很容易发现这个源代码下载的网址是在google上的,所以呢,需要读者自行解决网络的问题哟。

这个代码是可以下载到读者想要的文件中哟,在ubuntu中新建一个专门用来存储gem5代码的文件夹,利用cd语句将命令行调至该文件夹,并运行如上代码,gem5的源代码就会在这个文件夹中出现了。之后的其他例子的编译以及运行都是要在这个文件夹中进行的哟。

3、第一个GEM5的建立

我们先来构建一个基本的x86系统。目前,您必须为每个要模拟的ISA分别编译gem5。此外,如果使用Ruby简介,则必须对每个缓存一致性协议进行单独的编译。
要构建gem5,我们将使用SCons。SCons使用SConstruct文件(gem5/SConstruct)设置许多变量,然后使用每个子目录中的SConscript文件查找和编译所有gem5源代码。
SCons在第一次执行时自动创建gem5/build目录。在这个目录中,您可以找到由SCons、编译器等生成的文件。对于用于编译gem5的每一组选项(ISA和缓存一致性协议),都有一个单独的目录。
build-opts目录中有许多默认编译选项。这些文件指定最初生成gem5时传递给SCons的参数。我们将使用X86默认值并指定要编译所有CPU模型。您可以查看文件build_opts/X86以查看Scons选项的默认值。也可以在命令行上指定这些选项以覆盖任何默认值。

scons build/X86/gem5.opt -j2

传递给SCons的主要参数是您想要构建的build/X86/gem5.opt。在本例中,我们正在构建gem5.opt(一个带有调试符号的优化二进制文件)。我们想在build/X86目录中构建gem5。由于该目录当前不存在,SCons将查看build_opts来查找x86的默认参数。(注意:我在这里使用-j2在我的机器上执行2个内核中的2内核的构建。你应该为你的机器选择一个合适的号码,通常是内核数量

输出应该像如下:

Checking for C header file Python.h... yes Checking for C library pthread... yes Checking for C library dl... yes Checking for C library util... yes Checking for C library m... yes Checking for C library python2.7... yes Checking for accept(0,0,0) in C++ library None... yes Checking for zlibVersion() in C++ library z... yes Checking for GOOGLE_PROTOBUF_VERIFY_VERSION in C++ library protobuf... yes Checking for clock_nanosleep(0,0,NULL,NULL) in C library None... yes Checking for timer_create(CLOCK_MONOTONIC, NULL, NULL) in C library None... no Checking for timer_create(CLOCK_MONOTONIC, NULL, NULL) in C library rt... yes Checking for C library tcmalloc... yes Checking for backtrace_symbols_fd((void*)0, 0, 0) in C library None... yes Checking for C header file fenv.h... yes Checking for C header file linux/kvm.h... yes Checking size of struct kvm_xsave ... yes Checking for member exclude_host in struct perf_event_attr...yes Building in /local.chinook/gem5/gem5-tutorial/gem5/build/X86 Variables file /local.chinook/gem5/gem5-tutorial/gem5/build/variables/X86 not found, using defaults in /local.chinook/gem5/gem5-tutorial/gem5/build_opts/X86 scons: done reading SConscript files. scons: Building targets ... [ISA DESC] X86/arch/x86/isa/main.isa -> generated/inc.d [NEW DEPS] X86/arch/x86/generated/inc.d -> x86-deps [ENVIRONS] x86-deps -> x86-environs [ CXX] X86/sim/main.cc -> .o .... .... .... [ SHCXX] nomali/lib/mali_midgard.cc -> .os [ SHCXX] nomali/lib/mali_t6xx.cc -> .os [ SHCXX] nomali/lib/mali_t7xx.cc -> .os [ AR] -> drampower/libdrampower.a [ SHCXX] nomali/lib/addrspace.cc -> .os [ SHCXX] nomali/lib/mmu.cc -> .os [ RANLIB] -> drampower/libdrampower.a [ SHCXX] nomali/lib/nomali_api.cc -> .os [ AR] -> nomali/libnomali.a [ RANLIB] -> nomali/libnomali.a [ CXX] X86/base/date.cc -> .o [ LINK] -> X86/gem5.opt scons: done building targets. **//这个语句的出现代表建立成功** 二、创建一个简单的配置脚本

这一部分将介绍如何为gem5设置一个简单的模拟脚本并首次运行gem5。(假设您已经完成了上一部分,并且已经使用可执行的build/X86/gem5.opt成功地构建了gem5。)

我们的配置脚本将为一个非常简单的系统建模。我们只有一个简单的CPU核心。此CPU核心将连接到系统范围的内存总线。我们将有一个DDR3内存通道,也连接到内存总线。

1、GEM5的配置文件

gem5二进制文件将设置和执行模拟的python脚本作为参数。在此脚本中,接下来将创建一个要模拟的系统,创建系统的所有组件,并指定系统组件的所有参数。然后,从脚本开始模拟。

此脚本完全由用户定义。您可以选择在配置脚本中使用任何有效的Python代码。Learning_gem5提供了一个在Python中严格依赖类和继承的样式的示例。作为一个gem5用户,配置脚本的制作是简单还是复杂取决于您。

configs/examples中有许多示例配置脚本随gem5一起提供。大多数脚本都是全方位的,允许用户在命令行中指定几乎所有的选项。接下来将从运行gem5并从中构建的最简单的脚本开始,而不是从这些复杂的脚本开始。

2、创建一个配置文件

将命令行调到刚刚下载的gem5的文件夹下(利用cd语句),在这个文件夹下创建configs/tutorial 以及 configs/tutorial/simple.py

mkdir configs/tutorial touch configs/tutorial/simple.py

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

gem5的模块化设计是围绕SimObject类型构建的。
模拟系统中的大部分组件是SimObjects:
CPU、高速缓存、内存控制器、总线等等。

GEM5将所有这些对象从C++实现到Python。
因此,从python配置脚本可以创建任何SimObject,设置其参数,并指定SimObject之间的交互。
更多信息请参见文档

接下来要模拟的简单系统的结构示意图如下:
系统结构示意图

以下是对总体代码的分步解释:

(1)导入m5库以及我们编译的所有SimObjects:

import m5 from m5.objects import *

(2)创建第一个SimObject(我们将要模拟的系统-system,system对象将是模拟系统中所有其他对象的父对象。系统对象包含许多功能(而非时序级别)信息,如物理内存范围根时钟域根电压域内核(在完整系统模拟中)等。要创建system(SimObject),我们只需将其实例化为一个普通的python类:

system = System()

(3)在系统上设置时钟:首先要创建一个时钟域,然后我们可以在那个域上设置时钟频率。最后,为这个时钟域指定一个电压域。因为我们现在不关心系统电源,所以我们只使用电压域的默认选项

system.clk_domain = SrcClockDomain() system.clk_domain.clock = '1GHz' system.clk_domain.voltage_domain = VoltageDomain()

(4)接下来设置如何模拟内存:使用 timing 模式进行内存模拟,除了在特殊情况下(如快速转发和从检查点还原),您几乎总是将 timing 模式用于内存模拟。接下来将建立一个512MB大小的单一内存范围

system.mem_mode = 'timing' system.mem_ranges = [AddrRange('512MB')]

(5)创建一个CPU:从gem5中最简单的基于 timing 的CPU(TimingSimpleCPU)开始,这个CPU模型在一个时钟周期内执行每一条指令来执行,除了通过内存系统的内存请求

system.cpu = TimingSimpleCPU()

(6)创建系统范围内存总线:

system.membus = SystemXBar()

(7)有了内存总线,将CPU上的缓存端口连接到它。在这种情况下,由于我们要模拟的系统没有任何缓存,因此我们将I-cache和D-cache端口直接连接到membus。I-cache和D-cache的区别

system.cpu.icache_port = system.membus.slave system.cpu.dcache_port = system.membus.slave

(8)在CPU上创建一个I/O控制器并将其连接到内存总线。另外,我们需要在系统中连接一个特殊的端口到membus。此端口是仅允许系统读写内存的功能端口。

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

system.cpu.createInterruptController() if m5.defines.buildEnv['TARGET_ISA'] == "x86": system.cpu.interrupts[0].pio = system.membus.master system.cpu.interrupts[0].int_master = system.membus.slave system.cpu.interrupts[0].int_slave = system.membus.master system.system_port = system.membus.slave

要将内存系统组件连接在一起,gem5使用端口抽象。每个内存对象可以有两种端口:主端口和从端口。请求从主端口发送到从端口,响应从从端口发送到主端口。连接端口时,必须将主端口连接到从端口。
例如:memobject1.master = memobject2.slave
主设备和从设备可以位于=的任意一侧,并且将建立相同的连接。建立连接后,主机可以向从端口发送请求。

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

system.mem_ctrl = DDR3_1600_8x8() system.mem_ctrl.range = system.mem_ranges[0] system.mem_ctrl.port = system.membus.master

(10)设置CPU执行的进程:我们是在syscall仿真模式(SE模式)下执行的,所以我们只将CPU指向编译的可执行文件即可。我们将执行一个简单的“Hello world”程序,已经有一个是与gem5一起发布的,所以我们将使用它。您也可以指定为x86构建且已静态编译的任何应用程序。

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

process = Process() process.cmd = ['tests/test-progs/hello/bin/x86/linux/hello'] system.cpu.workload = process system.cpu.createThreads()

(11)我们需要做的最后一件事是实例化系统并开始执行。首先,我们创建 root 对象。然后我们实例化仿真。实例化过程遍历了我们在Python中创建的所有Simobjects,并创建了C++等价物. 注意,您不必实例化python类,然后显式地将参数指定为成员变量。您还可以将参数作为命名参数传递,如下面的 root 对象。

root = Root(full_system = False, system = system) m5.instantiate()

(12)打印模拟状态

print("Beginning simulation!") exit_event = m5.simulate() print('Exiting @ tick {} because {}' .format(m5.curTick(), exit_event.getCause())) 3、运行GEM5

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

build/X86/gem5.opt configs/tutorial/simple.py

运行结果如下:

gem5 Simulator System. http://gem5.org gem5 is copyrighted software; use the --copyright option for details. gem5 compiled Feb 15 2020 22:57:42 gem5 started Feb 18 2020 15:08:04 gem5 executing on VM-16-14-ubuntu, pid 8330 command line: build/X86/gem5.opt configs/tutorial/simple.py Global frequency set at 1000000000000 ticks per second 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 7000 Beginning simulation! info: Entering event queue @ 0. Starting simulation... Hello world! Exiting @ tick 454507000 because exiting with last active thread context 4、总结

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

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

GEM5系列教程索引

GEM5教程–gem5开始之旅(一)

GEM5教程–gem5开始之旅(二)

GEM5教程–修改和拓展gem5(一)


作者:人间之清欢



gem 教程

需要 登录 后方可回复, 如果你还没有账号请 注册新账号