在这里,我想搭建的是一个如下图的结构模型,这个结构模型中暂时没有考虑cache等复杂结构。
首先要做的是在 gem5/configs中新建一个py脚本文件,然后在脚本文件中写入配置信息。
然后我们要在这个文件中引入m5包和我们编译好的文件,并创建一个system对象。
import m5
from m5.objects import *
system = System()
然后这里我推荐一下gem5的官方文档,这这里可以找到自己需要使用的类和函数
http://www.gem5.org/docs/html/index.html
在这个架构中,我们首先要模拟的是的是时钟信息,在这里首先要创建一个 clock domain对象,然后进行时钟信息配置。查找官方文档,找到Srcclockdomain类库。
http://www.gem5.org/docs/html/classSrcClockDomain.html#details
创建完clock domain 对象后,要进行频率和电压的配置(这里先不考虑电压问题,所以使用默认电压)http://www.gem5.org/docs/html/classVoltageDomain.html
system.clk_domain = SrcClockDomain()
system.clk_domain.clock = '1GHz'
system.clk_domain.voltage_domain = VoltageDomain()
模拟完时钟后,进行内存的模拟。在进行内存模拟时需要进行模式和大小的配置,模式一般都配置为timing mode。(后续如果碰到需要配置为其他模式的时候会进行补充)
system.mem_mode = 'timing'
system.mem_ranges = [AddrRange('512MB')]
然后是CPU的模拟,因为这只是做开始的一个小测试,使用的是最简单的基于时序的CPU,然后是membus系统总线的创建和CPUcache端口的链接:
system.cpu = TimingSimpleCPU()
system.membus = SystemXBar()
system.cpu.icache_port = system.membus.slave
system.cpu.dcache_port = system.membus.slave
然后是模拟控制端口,x86架构中需要3条中断的端口线路,arm等不需要:
system.cpu.createInterruptController()
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
最后是进行内存控制器的模拟,这里采用DDR3的模拟控制器:
system.mem_ctrl = DDR3_1600_8x8()
system.mem_ctrl.range = system.mem_ranges[0]
system.mem_ctrl.port = system.membus.master
到此,就已经完成了上文中图片中简单系统的模拟。
接下来就是加载测试进程,并且输出系统中的状态信息:
process = Process()
process.cmd = ['tests/test-progs/hello/bin/x86/linux/hello']
system.cpu.workload = process
system.cpu.createThreads()
print("Beginning simulation!")
exit_event = m5.simulate()
print('Exiting @ tick {} because {}'.format(m5.curTick(), exit_event.getCause()))
在这里,我们需要搭建的系统架构如下图所示:
其中和上文中的单一系统不同的是增加了cache缓存i 机制。
在上述文件夹中新建一个 cache.py文件并按照http://learning.gem5.org/book/part1/cache_config.html中的提示进行搭建,代码的最后结果是:
from m5.objects import Cache
# Some specific options for caches
# For all options see src/mem/cache/Cache.py
class L1Cache(Cache):
"""Simple L1 Cache with default values"""
# Default parameters for both L1 I and D caches
assoc = 2
tag_latency = 2
data_latency = 2
response_latency = 2
mshrs = 4
tgts_per_mshr = 20
def connectCPU(self, cpu):
"""Connect this cache's port to a CPU-side port
This must be defined in a subclass"""
raise NotImplementedError
def connectBus(self, bus):
"""Connect this cache to a memory-side bus"""
self.mem_side = bus.slave
class L1ICache(L1Cache):
"""Simple L1 instruction cache with default values"""
# Set the default size
size = '16kB'
def connectCPU(self, cpu):
"""Connect this cache's port to a CPU icache port"""
self.cpu_side = cpu.icache_port
class L1DCache(L1Cache):
"""Simple L1 data cache with default values"""
# Set the default size
size = '64kB'
def connectCPU(self, cpu):
"""Connect this cache's port to a CPU dcache port"""
self.cpu_side = cpu.dcache_port
class L2Cache(Cache):
"""Simple L2 Cache with default values"""
# Default parameters
size = '256kB'
assoc = 8
tag_latency = 20
data_latency = 20
response_latency = 20
mshrs = 20
tgts_per_mshr = 12
def connectCPUSideBus(self, bus):
""""Connect this cache to a cpu-side bus"""
self.cpu_side = bus.master
def connectMemSideBus(self, bus):
""""Connect this cache to a memory-side bus"""
self.mem_side = bus.slave
然后复制一个simple.py文件并命名为two_level.py,在two_level.py文件中做如下更改:
system.cpu = TimingSimpleCPU()
system.membus = SystemXBar()
system.cpu.icache = L1ICache()
system.cpu.dcache = L1DCache()
system.cpu.icache.connectCPU(system.cpu)
system.cpu.dcache.connectCPU(system.cpu)
system.l2bus = L2XBar()
system.cpu.icache.connectBus(system.l2bus)
system.cpu.dcache.connectBus(system.l2bus)
system.l2cache = L2Cache()
system.l2cache.connectCPUSideBus(system.l2bus)
system.l2cache.connectMemSideBus(system.membus)
#system.cpu.icache_port = system.membus.slave
#system.cpu.dcache_port = system.membus.slave
接下俩是Using se.py and fs.py
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 --caches
此时发现,tick总时间更少啦~~证明cache使用成功~~
通过
build/X86/gem5.opt configs/example/se.py --help
可以查看帮助信息~~
至此gem5的入门操作就算是完成了,通过这次的学习,学会了用gem5来模拟简单的system和带有cache的system。通过这个学习发现gem5更多的是一个工具,更加重要的是如何去搭建这个系统。举个很简单的例子,gem5的使用更像是学习编程语言的语法,而系统的构建更类似于算法的学习。工具很重要,但是工具是用来干活的~~在跟着官方文档的三部曲完成gem5的基础学习后,会进行进一步计算机体系结构的学习~~