Gem5-添加缓存(上)

在配置脚本中添加缓存

以前面的配置脚本为起点,本章将讲述一个更复杂的配置。我们将为系统添加一个缓存层次结构,如下图所示。此外,本章还将介绍如何理解gem5的统计输出,以及如何在脚本中添加命令行参数。

创建缓存对象

我们将使用经典的缓存,而不是ruby-intro-chapter,因为我们正在为一个单CPU系统建模,而且我们并不关心缓存的一致性建模。我们将扩展Cache SimObject并为我们的系统配置它。首先,我们必须了解用于配置Cache对象的参数。

经典缓存模型和Ruby模型

gem5目前有两个完全不同的子系统来模拟系统中的片上缓存,即 "经典缓存 "和 "Ruby"。其历史原因是,gem5是由密歇根州的m5和威斯康星州的GEMS组合而成。GEMS使用Ruby作为其缓存模型,而经典缓存则来自于m5的代码库(因此称为 "经典")。这两种模型的区别在于,Ruby的设计是为了详细地模拟缓存的一致性。Ruby的一部分是SLICC,一种用于定义缓冲区一致性协议的语言。另一方面,经典缓存实现了一个简化的、不灵活的MOESI一致性协议。

要选择使用哪种模型,你应该问自己,你要建模的是什么。如果你正在模拟缓存一致性协议的变化,或者一致性协议可能对你的结果产生一阶影响,那么就使用Ruby。否则,如果一致性协议对你来说并不重要,就使用经典缓存。

gem5的一个长期目标是将这两种缓存模型统一为一个整体模型。

缓存

在 src/mem/cache/Cache.py 中可以找到 Cache SimObject 的声明。这个Python文件定义了你可以为SimObject设置的参数。在引擎盖下,当SimObject被实例化时,这些参数被传递给对象的C++实现。Cache SimObject继承于BaseCache对象,如下图所示。

在BaseCache类中,有很多的参数。例如,assoc是一个整数参数。一些参数,比如write_buffers有一个默认值,在这个例子中是8。默认参数是Param.*的第一个参数,除非第一个参数是一个字符串。每个参数的字符串参数是对该参数的描述(例如,tag_latency = Param.Cycles("Tag lookup latency")意味着tag_latency控制 "该缓存的命中延迟")。

这些参数中有很多没有默认值,所以我们需要在调用m5.instantiate()之前设置这些参数。

现在,为了创建具有特定参数的缓存,我们首先要在simple.py的同一目录下创建一个新的文件,caches.py,configs/tutorial/part1。第一步是在这个文件中导入我们要扩展的SimObject(s)。

from m5.objects import Cache

接下来,我们可以像对待其他Python类一样对待BaseCache对象,并扩展它。我们可以给新的缓存命名任何我们想要的东西。让我们从制作一个 L1 缓存开始。

class L1Cache(Cache):

assoc = 2

tag_latency = 2

data_latency = 2

response_latency = 2

mshrs = 4

tgts_per_mshr = 20

在这里,我们正在设置BaseCache的一些没有默认值的参数。要看到所有可能的配置选项,并找到哪些是必须的,哪些是可选的,你必须看一下SimObject的源代码。在这个例子中,我们使用的是BaseCache。

我们扩展了BaseCache,并在BaseCache的SimObject中设置了大部分没有默认值的参数。接下来,让我们再来看看L1Cache的两个子类,一个L1DCache和L1ICache。

class L1ICache(L1Cache):

size = '16kB'

class L1DCache(L1Cache):

size = '64kB'

让我们也来创建一个具有一些合理参数的二级缓存。

class L2Cache(Cache):

size = '256kB'

assoc = 8

tag_latency = 20

data_latency = 20

response_latency = 20

mshrs = 20

tgts_per_mshr = 12

现在我们已经指定了BaseCache所需的所有必要参数,我们要做的就是将我们的子类实例化并将缓存连接到互连上。然而,将大量的对象连接到复杂的互连上会使配置文件迅速增长,变得不可读。因此,让我们首先给我们的Cache的子类添加一些辅助函数。记住,这些只是Python类,所以我们可以用它们做任何你可以用Python类做的事情。

在L1缓存中,我们添加两个函数,connectCPU来连接CPU到缓存,connectBus来连接缓存到总线。我们需要在L1Cache类中添加以下代码。

def connectCPU(self, cpu):

# need to define this in a base class!

raise NotImplementedError

def connectBus(self, bus):

self.mem_side = bus.cpu_side_ports

接下来,我们必须为指令缓存和数据缓存定义一个单独的connectCPU函数,因为I缓存和D缓存的端口有不同的名字。我们的L1ICache和L1DCache类现在变成了:

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

最后,让我们为L2Cache添加函数,分别连接到内存侧和CPU侧的总线。

def connectCPUSideBus(self, bus):

self.cpu_side = bus.mem_side_ports

def connectMemSideBus(self, bus):

self.mem_side = bus.cpu_side_ports

完整的文件可以在gem5源代码中找到,地址是configs/learning_gem5/part1/caches.py。

 作者:速易芯李昊翔

更多详细文章可关注公众号 “速易芯Fastchip” !

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

速易芯Fastchip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值