Introdução ao GEM5

1 Introdução ao GEM5

gem5 é um simulador de arquitetura de computador de código aberto, incluindo arquitetura em nível de sistema e microarquitetura de processador. O predecessor do gem5 é o projeto m5 da Universidade de Michigan e o projeto GEMS da Universidade de Wisconsin. Em 2011, o m5 se fundiu com o GEMS para formar o gem5, que agora é amplamente utilizado na academia e na indústria. De acordo com o Google Scholar, o gem5 foi citado mais de 5.000 vezes, e um grande número de artigos usa o gem5 como ferramenta de pesquisa. Também é usado por muitas empresas industriais, incluindo ARM, AMD, Google, Micron, Metempsy, HP, Samsung, etc. Muitas empresas também adicionaram ativamente novos recursos ou melhoraram os existentes ao gem5. Nos últimos anos, a comunidade gem5 ainda está atualizando e desenvolvendo ativamente para apoiar a pesquisa de arquitetura de computadores pelos próximos 15 anos.

2 compilar

Obtenha o código-fonte do gem5:

git clone https://gem5.googlesource.com/public/gem5

Compilar:

scons build/X86/gem5.opt -j24

O comando de compilação é scons build/<CONFIG>/gem5.<buildtype>

Dentre eles, CONFIG é o tipo de processador a ser especificado, podendo ser especificadas as seguintes opções:

  • X86

  • BRAÇO

  • RISCV

  • MIPS

  • PODER

  • SPARC

  • ALL e NULL

  • GCN3_X86 (Modelo de GPU)

  • VEGA_X86 (Modelo de GPU)

buildtype é o tipo binário compilado e as seguintes opções podem ser especificadas:

  • debug: não otimiza e gera símbolos de depuração (-g)

  • opt: usa otimização de compilação e gera símbolos de depuração (-O3 -g)

  • rápido: Use todas as otimizações de compilação sem gerar símbolos de depuração (-O3)

O arquivo binário após a compilação é /build/X86/gem5.opt

3 Execute o script

3.1 Executando um sistema simples

GEM5 pode usar scripts Python para configurar o sistema a ser simulado. Esta seção construirá um sistema simples da seguinte forma: apenas CPU, barramento e controle de memória estão incluídos.

O roteiro é o seguinte:

# file: configs/tutorial/part1/simple.py

import m5
from m5.objects import *

# 创建系统,并进行初始化
# “system”对象是仿真系统中所有其他对象的父对象,其中包含了很多的功能信息,
# 如物理内存的范围、根时钟域、根电压域、full-system仿真下的kernel等
system = System()

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

# 设置内存仿真模式
system.mem_mode = 'timing'
system.mem_ranges = [AddrRange('512MB')]

# 创建CPU
system.cpu = X86TimingSimpleCPU()

# 创建系统总线
system.membus = SystemXBar()

# 不使用cache,直接将cpu的icache、dcache接口连接到membus上
#               +------------------+
#               |       cpu        |
#               +--+-----------+---+
#                  ^           ^
#  cpu.dcache_port |           | cpu.icache_port
#                  |           |
#                  V           V
#               +--+-----------+---+
#               |   membus         |
#               +------------------+
system.cpu.icache_port = system.membus.cpu_side_ports
system.cpu.dcache_port = system.membus.cpu_side_ports

# 创建一个IO Controller,并互联一些额外的线
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

# 创建内存控制器,memory controller
# 并连接memctrl到membus上
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

Neste ponto, o sistema foi construído e a próxima etapa é executar o sistema e executar um programa simples "Hello world" no sistema.

gem5 suporta dois modos de operação, um sistema completo e uma emulação syscall:

  • Sistema Completo (Modo FS): Simule todo o sistema de hardware e execute o kernel. O modo Full System completo é semelhante à execução de uma máquina virtual.

  • Emulação Syscall (Modo SE): Não emula todos os dispositivos do sistema, mas foca em emular a CPU e a memória do sistema, portanto não é necessário criar todos os dispositivos de hardware na hora de montar o sistema, podendo apenas emular Linux chamadas do sistema, ou seja, apenas simular o código do modo de usuário.

O arquivo Python acima criou um sistema simples e, em seguida, você precisa continuar a especificar o programa em execução no arquivo Python acima:

# 接着上面的python文件

# 指定需要运行的二进制程序,此处使用gem5中自带的"hello"程序
binary = 'tests/test-progs/hello/bin/x86/linux/hello'
system.workload = SEWorkload.init_compatible(binary)

# 创建process对象,并设置cpu的workload
process = Process()
process.cmd = [binary]
system.cpu.workload = process
system.cpu.createThreads()

# 最后,需要创建系统实例,并且运行仿真
root = Root(full_system = False, system = system)
m5.instantiate()

# 开始执行仿真
print("Beginning simulation!")
exit_event = m5.simulate()

print('Exiting @ tick {} because {}'.format(m5.curTick(), exit_event.getCause()))

Agora que o script está completo, execute o script de simulação no terminal:

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

O log de execução é o seguinte:

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

gem5 version 22.1.0.0
gem5 compiled Feb 27 2023 20:11:09
gem5 started Feb 28 2023 19:11:34
gem5 executing on ubuntu, pid 189423
command line: build/X86/gem5.opt configs/tutorial/part1/simple.py

Global frequency set at 1000000000000 ticks per second
build/X86/mem/dram_interface.cc:690: 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!
build/X86/sim/simulate.cc:192: info: Entering event queue @ 0.  Starting simulation...
Hello world!
Exiting @ tick 454646000 because exiting with last active thread context

Além disso, gem5 pode simular outras instruções de CPU, e criar uma CPU também pode especificar outros tipos de CPU da seguinte forma:

ISAs

Tipo de CPU

Risco

Braço

X86

Sparc

Poder

Mips

AtomicSimpleCPU

O3CPU

TimingSimpleCPU

KvmCPU

menorCPU

3.2 Adicionar Cache ao sistema

O exemplo no capítulo acima simula um sistema sem cache. O conteúdo desta seção adiciona L1Data Cache, L1Inst Cache e Unified L2 Cache com base no sistema Simples acima, conforme mostrado na figura abaixo.

O GEM5 pode simular dois tipos de cache "Caches clássicos" e "Ruby". Por razões históricas, o gem5 é mesclado com o projeto m5 e o projeto GEMS.O cache herdado do m5 é chamado de cache clássico, e o projeto GEMS usa o modelo de cache "Ruby". As diferenças entre os dois modelos de Cache são:

  • Ruby: Ruby é projetado para modelar a coerência do cache em detalhes, usando a modelagem SLICC. SLICC é uma linguagem de propósito especial para definir protocolos de coerência de cache.

  • Clasic: o cache do Calsic implementa um protocolo de coerência MOESI simplificado.

Para construir a estrutura do Cache, você precisa modificar o script anterior, local do arquivo: configs/tutorial/part1/cache.py

# file: configs/tutorial/part1/cache.py

import m5
from m5.objects import *

# 首先创建cache的类来方便进行cache的设置
# Base L1Cache 继承于Cache
class L1Cache(Cache):
    assoc = 2
    tag_latency = 2
    data_latency = 2
    response_latency = 2
    mshrs = 2
    tgts_per_mshr = 20
    
    def connectCPU(self, cpu):
        # 将在子类中重载
        raise NotImplementedError
    def connectBus(self, bus):
        self.mem_side = bus.cpu_side_ports
    
class L1ICache(L1Cache):
    size = '16kB'
    def connectCPU(self, cpu):
        self.cpu_side = cpu.icache_port
    
class L1DCache(L1Cache):
    size = '64kB'
    def connectCPU(self, cpu):
        self.cpu_side = cpu.dcache_port
    
# Base L2Cache 继承于Cache
class L2Cache(Cache):
    size = '256kB'
    assoc = 8
    tag_latency = 20
    data_latency = 20
    response_latency = 20
    mshrs = 20
    tgts_per_mshr = 12    
    def connectCPUSideBus(self, bus):
        self.cpu_side = bus.mem_side_ports
    def connectMemSideBus(self, bus):
        self.mem_side = bus.cpu_side_ports

# 创建系统,并进行初始化
# “system”对象是仿真系统中所有其他对象的父对象,其中包含了很多的功能信息,
# 如物理内存的范围、根时钟域、根电压域、full-system仿真下的kernel等
system = System()

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

# 设置内存仿真模式
system.mem_mode = 'timing'
system.mem_ranges = [AddrRange('512MB')]

# 创建CPU
system.cpu = X86TimingSimpleCPU()

# 创建并连接CPU的icache和dcache
#                +----------------------+
#                |       cpu            |
#                +--+---------------+---+
#  cpu.dcache_port  ^               ^ cpu.icache_port
#                   |               |
# L1DCache.cpu_side V               V L1ICache.cpu_side
#             +-----+-----+   +-----+-----+
#             | L1DCache  |   | L1DCache  |
#             +-----------+   +-----------+
system.cpu.icache = L1ICache()
system.cpu.dcache = L1DCache()
system.cpu.icache.connectCPU(system.cpu)
system.cpu.dcache.connectCPU(system.cpu)

# 创建并连接L2bus
#                +-----------+   +-----------+
#                | L1DCache  |   | L1ICache  |
#                +-----+-----+   +-----+-----+
#    L1DCache.mem_side ^               ^ L1ICache.mem_side
#                      |               |
# l2bus.cpu_side_ports V               V l2bus.cpu_side_ports
#                 +----+---------------+-----+
#                 |     L2 Bus               |
#                 +--------------------------+
system.l2bus = L2XBar()
system.cpu.icache.connectBus(system.l2bus)
system.cpu.dcache.connectBus(system.l2bus)

# 创建并连接L2Cache
#  +--------------------+
#  |     L2Bus          |
#  +---------+----------+
#            ^ L2Bus.mem_side_ports
#            |
#            V L2Cache.cpu_side
#  +---------+----------+
#  |     L2Cache        |
#  +---------+----------+
#            ^ L2Cache.mem_side
#            |
#            V MemBus.cpu_side_ports
#  +---------+----------+
#  |     MemBus        |
#  +--------------------+
system.l2cache = L2Cache()
system.l2cache.connectCPUSideBus(system.l2bus)
system.membus = SystemXBar()
system.l2cache.connectMemSideBus(system.membus)

# 创建一个IO Controller,并互联一些额外的线
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

# 创建内存控制器,memory controller
# 并连接memctrl到membus上
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

# 指定需要运行的二进制程序,此处使用gem5中自带的"hello"程序
binary = 'tests/test-progs/hello/bin/x86/linux/hello'
system.workload = SEWorkload.init_compatible(binary)

# 创建process对象,并设置cpu的workload
process = Process()
process.cmd = [binary]
system.cpu.workload = process
system.cpu.createThreads()

# 最后,需要创建系统实例,并且运行仿真
root = Root(full_system = False, system = system)
m5.instantiate()

# 开始执行仿真
print("Beginning simulation!")
exit_event = m5.simulate()

print('Exiting @ tick {} because {}'.format(m5.curTick(), exit_event.getCause()))

Execute com o seguinte comando:

build/X86/gem5.opt configs/tutorial/part1/cache.py

O log de execução é o seguinte:

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

gem5 version 22.1.0.0
gem5 compiled Feb 27 2023 20:11:09
gem5 started Feb 28 2023 19:12:49
gem5 executing on ubuntu, pid 189659
command line: build/X86/gem5.opt configs/tutorial/part1/cache.py

Global frequency set at 1000000000000 ticks per second
build/X86/mem/dram_interface.cc:690: 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!
build/X86/sim/simulate.cc:192: info: Entering event queue @ 0.  Starting simulation...
Hello world!
Exiting @ tick 56435000 because exiting with last active thread context

3.3 Arquivos de saída

Após a conclusão da operação, o arquivo de saída da operação do sistema será armazenado em m5out no caminho atual:

[qihangkong@ubuntu gem5]$ ls m5out/
config.dot  config.dot.pdf  config.dot.svg  config.ini config.json stats.txt

Um total de três tipos de arquivos são produzidos:

  • config.dot, config.dot.pdf, config.dot.svg:系统结构图

  • config.ini, config.json:详细的系统配置文件,将会显示所有系统中配置的模块

  • stats.txt:详细的运行统计数据,这个对我们进行性能分析很有帮助

4 使用默认的配置脚本

4.1 现有的脚本

GEM5中已经有了很多的已经构建好的系统脚本,可以直接使用,其存放位置就在 configs/ 目录下。

  • boot/:存放FS模式下的rcS启动脚本。

  • commom/:存放一些帮助脚本和函数脚本,如Caches.py。

  • dram/:存放测试DRAM的脚本

  • example/:存放一些例子脚本,如se.py、fs.py

  • learning_gem5/:存放learning gem5的例子

  • .....

4.2 使用se.py和fs.py

gem5提供了两个全面的脚本,se.py和fs.py用来模拟SE模式和FS模式。

如可以直接使用:

build/X86/gem5.opt configs/example/se.py --cmd=tests/test-progs/hello/bin/x86/linux/hello

或者可以指定CPU类型和L1cache的大小:

build/X86/gem5.opt configs/example/se.py --cmd=tests/test-progs/hello/bin/x86/linux/hello --cpu-type=TimingSimpleCPU --l1d_size=64kB --l1i_size=16kB

可以直接查看帮助文档:

build/X86/gem5.opt configs/example/se.py --help

参考资料:

Acho que você gosta

Origin blog.csdn.net/u014756627/article/details/129131816
Recomendado
Clasificación